in hw/display/exynos4210_fimd.c [1374:1682]
static void exynos4210_fimd_write(void *opaque, hwaddr offset,
uint64_t val, unsigned size)
{
Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
unsigned w, i;
uint32_t old_value;
DPRINT_L2("write offset 0x%08x, value=%llu(0x%08llx)\n", offset,
(long long unsigned int)val, (long long unsigned int)val);
switch (offset) {
case FIMD_VIDCON0:
if ((val & FIMD_VIDCON0_ENVID_MASK) == FIMD_VIDCON0_ENVID_MASK) {
exynos4210_fimd_enable(s, true);
} else {
if ((val & FIMD_VIDCON0_ENVID) == 0) {
exynos4210_fimd_enable(s, false);
}
}
s->vidcon[0] = val;
break;
case FIMD_VIDCON1:
/* Leave read-only bits as is */
val = (val & (~FIMD_VIDCON1_ROMASK)) |
(s->vidcon[1] & FIMD_VIDCON1_ROMASK);
s->vidcon[1] = val;
break;
case FIMD_VIDCON2 ... FIMD_VIDCON3:
s->vidcon[(offset) >> 2] = val;
break;
case FIMD_VIDTCON_START ... FIMD_VIDTCON_END:
s->vidtcon[(offset - FIMD_VIDTCON_START) >> 2] = val;
break;
case FIMD_WINCON_START ... FIMD_WINCON_END:
w = (offset - FIMD_WINCON_START) >> 2;
/* Window's current buffer ID */
i = fimd_get_buffer_id(&s->window[w]);
old_value = s->window[w].wincon;
val = (val & ~FIMD_WINCON_ROMASK) |
(s->window[w].wincon & FIMD_WINCON_ROMASK);
if (w == 0) {
/* Window 0 wincon ALPHA_MUL bit must always be 0 */
val &= ~FIMD_WINCON_ALPHA_MUL;
}
exynos4210_fimd_trace_bppmode(s, w, val);
switch (val & FIMD_WINCON_BUFSELECT) {
case FIMD_WINCON_BUF0_SEL:
val &= ~FIMD_WINCON_BUFSTATUS;
break;
case FIMD_WINCON_BUF1_SEL:
val = (val & ~FIMD_WINCON_BUFSTAT_H) | FIMD_WINCON_BUFSTAT_L;
break;
case FIMD_WINCON_BUF2_SEL:
if (val & FIMD_WINCON_BUFMODE) {
val = (val & ~FIMD_WINCON_BUFSTAT_L) | FIMD_WINCON_BUFSTAT_H;
}
break;
default:
break;
}
s->window[w].wincon = val;
exynos4210_fimd_update_win_bppmode(s, w);
fimd_update_get_alpha(s, w);
if ((i != fimd_get_buffer_id(&s->window[w])) ||
(!(old_value & FIMD_WINCON_ENWIN) && (s->window[w].wincon &
FIMD_WINCON_ENWIN))) {
fimd_update_memory_section(s, w);
}
break;
case FIMD_SHADOWCON:
old_value = s->shadowcon;
s->shadowcon = val;
for (w = 0; w < NUM_OF_WINDOWS; w++) {
if (FIMD_WINDOW_PROTECTED(old_value, w) &&
!FIMD_WINDOW_PROTECTED(s->shadowcon, w)) {
fimd_update_memory_section(s, w);
}
}
break;
case FIMD_WINCHMAP:
s->winchmap = val;
break;
case FIMD_VIDOSD_START ... FIMD_VIDOSD_END:
w = (offset - FIMD_VIDOSD_START) >> 4;
i = ((offset - FIMD_VIDOSD_START) & 0xF) >> 2;
switch (i) {
case 0:
old_value = s->window[w].lefttop_y;
s->window[w].lefttop_x = (val >> FIMD_VIDOSD_HOR_SHIFT) &
FIMD_VIDOSD_COORD_MASK;
s->window[w].lefttop_y = (val >> FIMD_VIDOSD_VER_SHIFT) &
FIMD_VIDOSD_COORD_MASK;
if (s->window[w].lefttop_y != old_value) {
fimd_update_memory_section(s, w);
}
break;
case 1:
old_value = s->window[w].rightbot_y;
s->window[w].rightbot_x = (val >> FIMD_VIDOSD_HOR_SHIFT) &
FIMD_VIDOSD_COORD_MASK;
s->window[w].rightbot_y = (val >> FIMD_VIDOSD_VER_SHIFT) &
FIMD_VIDOSD_COORD_MASK;
if (s->window[w].rightbot_y != old_value) {
fimd_update_memory_section(s, w);
}
break;
case 2:
if (w == 0) {
s->window[w].osdsize = val;
} else {
s->window[w].alpha_val[0] =
unpack_upper_4((val & FIMD_VIDOSD_ALPHA_AEN0) >>
FIMD_VIDOSD_AEN0_SHIFT) |
(s->window[w].alpha_val[0] & FIMD_VIDALPHA_ALPHA_LOWER);
s->window[w].alpha_val[1] =
unpack_upper_4(val & FIMD_VIDOSD_ALPHA_AEN1) |
(s->window[w].alpha_val[1] & FIMD_VIDALPHA_ALPHA_LOWER);
}
break;
case 3:
if (w != 1 && w != 2) {
qemu_log_mask(LOG_GUEST_ERROR,
"FIMD: Bad write offset 0x%08"HWADDR_PRIx"\n",
offset);
return;
}
s->window[w].osdsize = val;
break;
}
break;
case FIMD_VIDWADD0_START ... FIMD_VIDWADD0_END:
w = (offset - FIMD_VIDWADD0_START) >> 3;
i = ((offset - FIMD_VIDWADD0_START) >> 2) & 1;
if (i == fimd_get_buffer_id(&s->window[w]) &&
s->window[w].buf_start[i] != val) {
s->window[w].buf_start[i] = val;
fimd_update_memory_section(s, w);
break;
}
s->window[w].buf_start[i] = val;
break;
case FIMD_VIDWADD1_START ... FIMD_VIDWADD1_END:
w = (offset - FIMD_VIDWADD1_START) >> 3;
i = ((offset - FIMD_VIDWADD1_START) >> 2) & 1;
s->window[w].buf_end[i] = val;
break;
case FIMD_VIDWADD2_START ... FIMD_VIDWADD2_END:
w = (offset - FIMD_VIDWADD2_START) >> 2;
if (((val & FIMD_VIDWADD2_PAGEWIDTH) != s->window[w].virtpage_width) ||
(((val >> FIMD_VIDWADD2_OFFSIZE_SHIFT) & FIMD_VIDWADD2_OFFSIZE) !=
s->window[w].virtpage_offsize)) {
s->window[w].virtpage_width = val & FIMD_VIDWADD2_PAGEWIDTH;
s->window[w].virtpage_offsize =
(val >> FIMD_VIDWADD2_OFFSIZE_SHIFT) & FIMD_VIDWADD2_OFFSIZE;
fimd_update_memory_section(s, w);
}
break;
case FIMD_VIDINTCON0:
s->vidintcon[0] = val;
break;
case FIMD_VIDINTCON1:
s->vidintcon[1] &= ~(val & 7);
exynos4210_fimd_update_irq(s);
break;
case FIMD_WKEYCON_START ... FIMD_WKEYCON_END:
w = ((offset - FIMD_WKEYCON_START) >> 3) + 1;
i = ((offset - FIMD_WKEYCON_START) >> 2) & 1;
s->window[w].keycon[i] = val;
break;
case FIMD_WKEYALPHA_START ... FIMD_WKEYALPHA_END:
w = ((offset - FIMD_WKEYALPHA_START) >> 2) + 1;
s->window[w].keyalpha = val;
break;
case FIMD_DITHMODE:
s->dithmode = val;
break;
case FIMD_WINMAP_START ... FIMD_WINMAP_END:
w = (offset - FIMD_WINMAP_START) >> 2;
old_value = s->window[w].winmap;
s->window[w].winmap = val;
if ((val & FIMD_WINMAP_EN) ^ (old_value & FIMD_WINMAP_EN)) {
exynos4210_fimd_invalidate(s);
exynos4210_fimd_update_win_bppmode(s, w);
exynos4210_fimd_trace_bppmode(s, w, 0xFFFFFFFF);
exynos4210_fimd_update(s);
}
break;
case FIMD_WPALCON_HIGH ... FIMD_WPALCON_LOW:
i = (offset - FIMD_WPALCON_HIGH) >> 2;
s->wpalcon[i] = val;
if (s->wpalcon[1] & FIMD_WPALCON_UPDATEEN) {
for (w = 0; w < NUM_OF_WINDOWS; w++) {
exynos4210_fimd_update_win_bppmode(s, w);
fimd_update_get_alpha(s, w);
}
}
break;
case FIMD_TRIGCON:
val = (val & ~FIMD_TRIGCON_ROMASK) | (s->trigcon & FIMD_TRIGCON_ROMASK);
s->trigcon = val;
break;
case FIMD_I80IFCON_START ... FIMD_I80IFCON_END:
s->i80ifcon[(offset - FIMD_I80IFCON_START) >> 2] = val;
break;
case FIMD_COLORGAINCON:
s->colorgaincon = val;
break;
case FIMD_LDI_CMDCON0 ... FIMD_LDI_CMDCON1:
s->ldi_cmdcon[(offset - FIMD_LDI_CMDCON0) >> 2] = val;
break;
case FIMD_SIFCCON0 ... FIMD_SIFCCON2:
i = (offset - FIMD_SIFCCON0) >> 2;
if (i != 2) {
s->sifccon[i] = val;
}
break;
case FIMD_HUECOEFCR_START ... FIMD_HUECOEFCR_END:
i = (offset - FIMD_HUECOEFCR_START) >> 2;
s->huecoef_cr[i] = val;
break;
case FIMD_HUECOEFCB_START ... FIMD_HUECOEFCB_END:
i = (offset - FIMD_HUECOEFCB_START) >> 2;
s->huecoef_cb[i] = val;
break;
case FIMD_HUEOFFSET:
s->hueoffset = val;
break;
case FIMD_VIDWALPHA_START ... FIMD_VIDWALPHA_END:
w = ((offset - FIMD_VIDWALPHA_START) >> 3);
i = ((offset - FIMD_VIDWALPHA_START) >> 2) & 1;
if (w == 0) {
s->window[w].alpha_val[i] = val;
} else {
s->window[w].alpha_val[i] = (val & FIMD_VIDALPHA_ALPHA_LOWER) |
(s->window[w].alpha_val[i] & FIMD_VIDALPHA_ALPHA_UPPER);
}
break;
case FIMD_BLENDEQ_START ... FIMD_BLENDEQ_END:
s->window[(offset - FIMD_BLENDEQ_START) >> 2].blendeq = val;
break;
case FIMD_BLENDCON:
old_value = s->blendcon;
s->blendcon = val;
if ((s->blendcon & FIMD_ALPHA_8BIT) != (old_value & FIMD_ALPHA_8BIT)) {
for (w = 0; w < NUM_OF_WINDOWS; w++) {
fimd_update_get_alpha(s, w);
}
}
break;
case FIMD_WRTQOSCON_START ... FIMD_WRTQOSCON_END:
s->window[(offset - FIMD_WRTQOSCON_START) >> 2].rtqoscon = val;
break;
case FIMD_I80IFCMD_START ... FIMD_I80IFCMD_END:
s->i80ifcmd[(offset - FIMD_I80IFCMD_START) >> 2] = val;
break;
case FIMD_VIDW0ADD0_B2 ... FIMD_VIDW4ADD0_B2:
if (offset & 0x0004) {
qemu_log_mask(LOG_GUEST_ERROR,
"FIMD: bad write offset 0x%08"HWADDR_PRIx"\n",
offset);
break;
}
w = (offset - FIMD_VIDW0ADD0_B2) >> 3;
if (fimd_get_buffer_id(&s->window[w]) == 2 &&
s->window[w].buf_start[2] != val) {
s->window[w].buf_start[2] = val;
fimd_update_memory_section(s, w);
break;
}
s->window[w].buf_start[2] = val;
break;
case FIMD_SHD_ADD0_START ... FIMD_SHD_ADD0_END:
if (offset & 0x0004) {
qemu_log_mask(LOG_GUEST_ERROR,
"FIMD: bad write offset 0x%08"HWADDR_PRIx"\n",
offset);
break;
}
s->window[(offset - FIMD_SHD_ADD0_START) >> 3].shadow_buf_start = val;
break;
case FIMD_SHD_ADD1_START ... FIMD_SHD_ADD1_END:
if (offset & 0x0004) {
qemu_log_mask(LOG_GUEST_ERROR,
"FIMD: bad write offset 0x%08"HWADDR_PRIx"\n",
offset);
break;
}
s->window[(offset - FIMD_SHD_ADD1_START) >> 3].shadow_buf_end = val;
break;
case FIMD_SHD_ADD2_START ... FIMD_SHD_ADD2_END:
s->window[(offset - FIMD_SHD_ADD2_START) >> 2].shadow_buf_size = val;
break;
case FIMD_PAL_MEM_START ... FIMD_PAL_MEM_END:
w = (offset - FIMD_PAL_MEM_START) >> 10;
i = ((offset - FIMD_PAL_MEM_START) >> 2) & 0xFF;
s->window[w].palette[i] = val;
break;
case FIMD_PALMEM_AL_START ... FIMD_PALMEM_AL_END:
/* Palette memory aliases for windows 0 and 1 */
w = (offset - FIMD_PALMEM_AL_START) >> 10;
i = ((offset - FIMD_PALMEM_AL_START) >> 2) & 0xFF;
s->window[w].palette[i] = val;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"FIMD: bad write offset 0x%08"HWADDR_PRIx"\n", offset);
break;
}
}