Skip to content

Commit f0b6998

Browse files
authored
video engine: Add HW scaler support, switch color format to YV12 (#95)
video engine: Add HW scaler support, Switch color format to YV12 as this is native format from libcedar Switch CSC to DISP_ YCC to fix color banding
1 parent 2eff272 commit f0b6998

1 file changed

Lines changed: 71 additions & 23 deletions

File tree

  • drivers/video/fbdev/sunxi

drivers/video/fbdev/sunxi/disp.c

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ struct __disp_fb_t {
4040
uint32_t mode;
4141
};
4242

43+
struct disp_rect {
44+
int x;
45+
int y;
46+
int width;
47+
int height;
48+
};
4349

4450
struct suniv_iomm {
4551
uint8_t *debe;
@@ -99,47 +105,89 @@ void debe_layer_set_mode(uint8_t layer, debe_color_mode_e mode)
99105
}
100106
}
101107

102-
103-
104-
static long disp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
108+
static inline uint32_t calc_scaling_factor(int input, int output)
105109
{
106-
uint32_t __user *uarg = (uint32_t __user *)arg;
110+
uint32_t ratio = (input << 16) / output;
111+
uint32_t int_part = (ratio >> 16) & 0xFF;
112+
uint32_t frac_part = ratio & 0xFFFF;
113+
return (int_part << 16) | frac_part;
114+
}
115+
116+
static long disp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
117+
uint32_t
118+
__user * uarg = (uint32_t
119+
__user *)arg;
107120
uint32_t tmp[4];
108121

109122
if (copy_from_user(tmp, uarg, sizeof(tmp)))
110123
return -EFAULT;
111124

112125
switch (cmd) {
113126

114-
case DISP_CMD_VERSION:
115-
tmp[0] = 0x202406;
116-
if (copy_to_user(uarg, tmp, sizeof(uint32_t)))
117-
return -EFAULT;
118-
break;
127+
case DISP_CMD_VERSION:
128+
tmp[0] = 0x202406;
129+
if (copy_to_user(uarg, tmp, sizeof(uint32_t)))
130+
return -EFAULT;
131+
break;
132+
133+
case DISP_CMD_LAYER_REQUEST:
134+
case DISP_CMD_LAYER_RELEASE:
135+
case DISP_CMD_LAYER_SET_PARA:
136+
case DISP_CMD_LAYER_GET_PARA:
137+
case DISP_CMD_LAYER_SET_SRC_WINDOW: {
138+
unsigned int __user
139+
*argp;
140+
unsigned int tmp[3];
141+
struct disp_rect *user_rect;
142+
struct disp_rect rect;
143+
argp = (unsigned int __user
144+
*)arg;
145+
if (copy_from_user(tmp, argp, sizeof(tmp)))
146+
return -EFAULT;
147+
user_rect = (struct disp_rect *) (uintptr_t) tmp[2];
148+
if (tmp[2] != 0) {
149+
if (copy_from_user(&rect, user_rect, sizeof(rect)))
150+
return -EFAULT;
151+
writel(rect.width, iomm.defe + DEFE_STRIDE0);
152+
writel(rect.width / 2, iomm.defe + DEFE_STRIDE1);
153+
writel(rect.width / 2, iomm.defe + DEFE_STRIDE2);
154+
writel((rect.width - 1) | ((rect.height - 1) << 16), iomm.defe + DEFE_IN_SIZE);
155+
writel((320 - 1) | ((240 - 1) << 16), iomm.defe + DEFE_OUT_SIZE);
156+
writel(calc_scaling_factor(rect.width, 320), iomm.defe + DEFE_H_FACT);
157+
158+
//Sunxi VPU aligns the buffer height to a multiple of 16 pixels.
159+
switch (rect.height) {
160+
case 256:
161+
writel(calc_scaling_factor(240, 240), iomm.defe + DEFE_V_FACT);
162+
break;
163+
case 384:
164+
writel(calc_scaling_factor(360, 240), iomm.defe + DEFE_V_FACT);
165+
break;
166+
default:
167+
writel(calc_scaling_factor(rect.height, 240), iomm.defe + DEFE_V_FACT);
168+
break;
169+
}
170+
}
171+
break;
172+
}
173+
119174

120-
case DISP_CMD_LAYER_REQUEST:
121-
case DISP_CMD_LAYER_RELEASE:
122-
case DISP_CMD_LAYER_SET_PARA:
123-
case DISP_CMD_LAYER_GET_PARA:
124-
case DISP_CMD_LAYER_SET_SRC_WINDOW:
125175
case DISP_CMD_LAYER_SET_SCN_WINDOW:
126176
break;
127177

128178
case DISP_CMD_LAYER_SET_FB:
129179
if (copy_from_user(&fb, (void __user *)tmp[2], sizeof(fb)))
130180
return -EFAULT;
131181
writel((uint32_t)(fb.addr[0] ), iomm.defe+DEFE_ADDR0);
182+
writel((uint32_t)(fb.addr[1] ), iomm.defe+DEFE_ADDR1);
183+
writel((uint32_t)(fb.addr[2] ), iomm.defe+DEFE_ADDR2);
184+
132185
break;
133186
case DISP_CMD_LAYER_OPEN:
134187
suniv_setbits(iomm.defe+DEFE_EN, 0x01); // Enable DEFE
135188
suniv_setbits(iomm.defe+DEFE_EN, (1 << 31)); // Enable CPU access
136189
writel((0 << 0) | (0 << 1), iomm.defe+DEFE_BYPASS); // CSC/scaler bypass disabled
137-
writel(320*2, iomm.defe+DEFE_STRIDE0);
138-
writel((320-1) | ((240-1) << 16), iomm.defe+DEFE_IN_SIZE);
139-
writel((320-1) | ((240-1) << 16), iomm.defe+DEFE_OUT_SIZE);
140-
writel((1 << 16), iomm.defe+DEFE_H_FACT); // H scale
141-
writel((1 << 16), iomm.defe+DEFE_V_FACT); // V scale
142-
writel( (1 << 8 ) | (1 << 4) | (1 << 0) , iomm.defe+DEFE_IN_FMT);
190+
writel( (0 << 8 ) | (2 << 4) | (0 << 0) , iomm.defe+DEFE_IN_FMT); // YV12
143191
suniv_setbits(iomm.defe+DEFE_FRM_CTRL, (1 << 23)); // Enable CPU access to filter RAM (if enabled, filter is bypassed?)
144192
suniv_clrbits(iomm.defe+DEFE_EN, (1 << 31)); // Disable CPU access (?)
145193
suniv_setbits(iomm.defe+DEFE_FRM_CTRL, (1 << 0)); // Registers ready
@@ -150,9 +198,9 @@ static long disp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
150198

151199
for(i = 0; i < 4; i++) // Color conversion table
152200
{
153-
writel(csc_tab[i], iomm.defe + DEFE_CSC_COEF + i * 4 + 0 * 4);
154-
writel(csc_tab[i + 4], iomm.defe + DEFE_CSC_COEF + i * 4 + 4 * 4);
155-
writel(csc_tab[i + 8], iomm.defe + DEFE_CSC_COEF + i * 4 + 8 * 4);
201+
writel(csc_tab[2 * 48 + i], iomm.defe + DEFE_CSC_COEF + i * 4 + 0 * 4);
202+
writel(csc_tab[2 * 48 + i + 4], iomm.defe + DEFE_CSC_COEF + i * 4 + 4 * 4);
203+
writel(csc_tab[2 * 48 + i + 8], iomm.defe + DEFE_CSC_COEF + i * 4 + 8 * 4);
156204
}
157205
suniv_setbits(iomm.debe + DEBE_REGBUFF_CTRL_REG, (1 << 0));
158206
break;

0 commit comments

Comments
 (0)