@@ -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
4450struct 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