1 /*
2 * Allwinner SoCs display driver.
3 *
4 * Copyright (C) 2016 Allwinner.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11 /**
12 * All Winner Tech, All Right Reserved. 2014-2015 Copyright (c)
13 *
14 * File name : de_gsu.c
15 *
16 * Description : display engine 2.0 gsu basic function definition
17 *
18 * History : 2014/03/20 vito cheng v0.1 Initial version
19 *
20 */
21 #include "de_feat.h"
22 #include "de_gsu_type.h"
23 #include "de_scaler.h"
24 #include "de_scaler_table.h"
25
26 static volatile struct __gsu_reg_t *gsu_dev[DE_NUM][UI_CHN_NUM];
27 static struct de_reg_blocks gsu_glb_block[DE_NUM][UI_CHN_NUM];
28 static struct de_reg_blocks gsu_out_block[DE_NUM][UI_CHN_NUM];
29 static struct de_reg_blocks gsu_scale_block[DE_NUM][UI_CHN_NUM];
30 static struct de_reg_blocks gsu_coeff_block[DE_NUM][UI_CHN_NUM];
31
de_gsu_init(unsigned int sel,uintptr_t reg_base)32 int de_gsu_init(unsigned int sel, uintptr_t reg_base)
33 {
34 int j, chno;
35 uintptr_t gsu_base;
36 void *memory;
37 int vi_chno;
38 int gsu_offset;
39
40 chno = de_feat_is_support_scale(sel);
41 vi_chno = de_feat_get_num_vi_chns(sel);
42 chno = chno - vi_chno;
43
44 gsu_offset = VSU_OFST + vi_chno * 0x20000;
45
46 for (j = 0; j < chno; j++) {
47 gsu_base = reg_base + (sel + 1) * 0x00100000 + gsu_offset
48 + j * 0x10000;
49 #if defined(CONFIG_ARCH_SUN50IW10)
50 if (sel)
51 gsu_base = gsu_base - 0x00100000;
52 #endif
53 #if defined(CONFIG_ARCH_SUN8IW15)
54 if (j > 0)
55 gsu_base += 0x10000;
56 #endif
57
58 memory = disp_sys_malloc(sizeof(struct __gsu_reg_t));
59 if (memory == NULL) {
60 DE_WRN("disp_sys_malloc uscaler[%d][%d] memory fail! size=0x%x\n",
61 sel,
62 j,
63 (unsigned int)sizeof(struct __gsu_reg_t));
64 return -1;
65 }
66
67 gsu_glb_block[sel][j].off = gsu_base;
68 gsu_glb_block[sel][j].val = memory;
69 gsu_glb_block[sel][j].size = 0x14;
70 gsu_glb_block[sel][j].dirty = 0;
71
72 gsu_out_block[sel][j].off = gsu_base + 0x40;
73 gsu_out_block[sel][j].val = memory + 0x40;
74 gsu_out_block[sel][j].size = 0x4;
75 gsu_out_block[sel][j].dirty = 0;
76
77 gsu_scale_block[sel][j].off = gsu_base + 0x80;
78 gsu_scale_block[sel][j].val = memory + 0x80;
79 gsu_scale_block[sel][j].size = 0x20;
80 gsu_scale_block[sel][j].dirty = 0;
81
82 gsu_coeff_block[sel][j].off = gsu_base + 0x200;
83 gsu_coeff_block[sel][j].val = memory + 0x200;
84 gsu_coeff_block[sel][j].size = 0x40;
85 gsu_coeff_block[sel][j].dirty = 0;
86
87 de_gsu_set_reg_base(sel, j, memory);
88 }
89
90 return 0;
91 }
92
de_gsu_exit(unsigned int sel)93 int de_gsu_exit(unsigned int sel)
94 {
95 int j, chno;
96 int vi_chno;
97
98 chno = de_feat_is_support_scale(sel);
99 vi_chno = de_feat_get_num_vi_chns(sel);
100 chno = chno - vi_chno;
101
102 for (j = 0; j < chno; j++)
103 disp_sys_free(gsu_glb_block[sel][j].val);
104
105 return 0;
106 }
107
de_gsu_update_regs(unsigned int sel)108 int de_gsu_update_regs(unsigned int sel)
109 {
110 int i, chno;
111
112 chno = de_feat_is_support_scale(sel);
113 chno = chno - de_feat_get_num_vi_chns(sel);
114
115 for (i = 0; i < chno; i++) {
116 if (gsu_glb_block[sel][i].dirty == 0x1) {
117 regwrite((void *)gsu_glb_block[sel][i].off,
118 gsu_glb_block[sel][i].val,
119 gsu_glb_block[sel][i].size);
120 gsu_glb_block[sel][i].dirty = 0x0;
121 }
122 if (gsu_out_block[sel][i].dirty == 0x1) {
123 regwrite((void *)gsu_out_block[sel][i].off,
124 gsu_out_block[sel][i].val,
125 gsu_out_block[sel][i].size);
126 gsu_out_block[sel][i].dirty = 0x0;
127 }
128 if (gsu_scale_block[sel][i].dirty == 0x1) {
129 regwrite((void *)gsu_scale_block[sel][i].off,
130 gsu_scale_block[sel][i].val,
131 gsu_scale_block[sel][i].size);
132 gsu_scale_block[sel][i].dirty = 0x0;
133 }
134 if (gsu_coeff_block[sel][i].dirty == 0x1) {
135 regwrite((void *)gsu_coeff_block[sel][i].off,
136 gsu_coeff_block[sel][i].val,
137 gsu_coeff_block[sel][i].size);
138 gsu_coeff_block[sel][i].dirty = 0x0;
139 }
140
141 }
142
143 return 0;
144 }
145
146 /**
147 * function : de_gsu_set_reg_base(unsigned int sel,
148 * unsigned int chno,
149 * void *base)
150 * description : set gsu reg base
151 * parameters :
152 * sel <rtmx select>
153 * chno <overlay select>
154 * base <reg base>
155 * return :
156 * success
157 */
de_gsu_set_reg_base(unsigned int sel,unsigned int chno,void * base)158 int de_gsu_set_reg_base(unsigned int sel, unsigned int chno, void *base)
159 {
160 DE_INF("sel=%d, chno=%d, base=0x%p\n", sel, chno, base);
161 gsu_dev[sel][chno] = (struct __gsu_reg_t *) base;
162
163 return 0;
164 }
165
166 /**
167 * function : de_gsu_enable(unsigned int sel,
168 * unsigned int chno, unsigned int en)
169 * description : enable/disable gsu
170 * parameters :
171 * sel <rtmx select>
172 * chno <overlay select>
173 * en <enable: 0-disable; 1-enable>
174 * return :
175 * success
176 */
de_gsu_enable(unsigned int sel,unsigned int chno,unsigned int en)177 int de_gsu_enable(unsigned int sel, unsigned int chno, unsigned int en)
178 {
179 gsu_dev[sel][chno - VI_CHN_NUM]->ctrl.bits.en = en;
180 gsu_glb_block[sel][chno - VI_CHN_NUM].dirty = 1;
181
182 return 0;
183 }
184
185 /**
186 * function : de_gsu_set_fir_coef(unsigned int sel,
187 * unsigned int chno,
188 * unsigned int *coef)
189 * description : set fir coefficients
190 * parameters :
191 * sel <rtmx select>
192 * chno <overlay select>
193 * *coef <coefficients pointer>
194 * return :
195 * success
196 */
197 /*static int de_gsu_set_fir_coef(unsigned int sel, unsigned int chno,
198 * unsigned int *coef)
199 *{
200 * regwrite(&gsu_dev[sel][chno-VI_CHN_NUM]->hcoeff, coef,
201 * sizeof(unsigned int)*GSU_PHASE_NUM);
202 *
203 * return 0;
204 *}
205 */
206
207 /*
208 * function : de_gsu_calc_fir_coef(unsigned int step)
209 * description : set fir coefficients
210 * parameters :
211 * step <horizontal scale ratio of gsu>
212 * return :
213 * offset (in word) of coefficient table
214 */
de_gsu_calc_fir_coef(unsigned int step)215 static unsigned int de_gsu_calc_fir_coef(unsigned int step)
216 {
217 unsigned int pt_coef;
218 unsigned int scale_ratio, int_part, float_part, fir_coef_ofst;
219
220 scale_ratio = step >> (GSU_PHASE_FRAC_BITWIDTH - 3);
221 int_part = scale_ratio >> 3;
222 float_part = scale_ratio & 0x7;
223 fir_coef_ofst = (int_part == 0) ? GSU_ZOOM0_SIZE :
224 (int_part == 1) ? GSU_ZOOM0_SIZE + float_part :
225 (int_part == 2) ? GSU_ZOOM0_SIZE + GSU_ZOOM1_SIZE
226 + (float_part >> 1) :
227 (int_part == 3) ? GSU_ZOOM0_SIZE + GSU_ZOOM1_SIZE
228 + GSU_ZOOM2_SIZE :
229 (int_part == 4) ? GSU_ZOOM0_SIZE + GSU_ZOOM1_SIZE
230 + GSU_ZOOM2_SIZE + GSU_ZOOM3_SIZE :
231 GSU_ZOOM0_SIZE + GSU_ZOOM1_SIZE + GSU_ZOOM2_SIZE
232 + GSU_ZOOM3_SIZE + GSU_ZOOM4_SIZE;
233
234 pt_coef = fir_coef_ofst * GSU_PHASE_NUM;
235
236 return pt_coef;
237 }
238
239 /**
240 * function : de_gsu_set_para(unsigned int sel, unsigned int chno,
241 * unsigned int *coef)
242 * description : set fir coefficients
243 * parameters :
244 * sel <rtmx select>
245 * chno <overlay select>
246 * *coef <coefficients pointer>
247 * return :
248 * success
249 */
de_gsu_set_para(unsigned int sel,unsigned int chno,unsigned int enable,unsigned int in_w,unsigned int in_h,unsigned int out_w,unsigned int out_h,struct scaler_para * para)250 int de_gsu_set_para(unsigned int sel, unsigned int chno, unsigned int enable,
251 unsigned int in_w, unsigned int in_h,
252 unsigned int out_w, unsigned int out_h,
253 struct scaler_para *para)
254 {
255 unsigned int pt_coef;
256 unsigned int chno_t;
257 unsigned int vi_chno;
258
259 vi_chno = de_feat_get_num_vi_chns(sel);
260
261 chno_t = chno - vi_chno;
262
263 gsu_dev[sel][chno_t]->ctrl.bits.en = enable;
264
265 if (enable == 0) {
266 gsu_glb_block[sel][chno_t].dirty = 1;
267 return 0;
268 }
269 /* basic parameter */
270 gsu_dev[sel][chno_t]->outsize.dwval = ((out_h - 1) << 16) | (out_w - 1);
271 gsu_dev[sel][chno_t]->insize.dwval = ((in_h - 1) << 16) | (in_w - 1);
272 gsu_dev[sel][chno_t]->hstep.dwval
273 = para->hstep << GSU_PHASE_FRAC_REG_SHIFT;
274 gsu_dev[sel][chno_t]->vstep.dwval
275 = para->vstep << GSU_PHASE_FRAC_REG_SHIFT;
276 gsu_dev[sel][chno_t]->hphase.dwval
277 = para->hphase << GSU_PHASE_FRAC_REG_SHIFT;
278 gsu_dev[sel][chno_t]->vphase0.dwval
279 = para->vphase << GSU_PHASE_FRAC_REG_SHIFT;
280
281 /* fir coefficient */
282 pt_coef = de_gsu_calc_fir_coef(para->vstep);
283 regwrite(((void *)&gsu_dev[sel][chno_t]->hcoeff),
284 lan2coefftab16 + pt_coef,
285 sizeof(unsigned int) * GSU_PHASE_NUM);
286 gsu_dev[sel][chno_t]->ctrl.bits.coef_switch_rdy = 1;
287 gsu_glb_block[sel][chno_t].dirty = 1;
288 gsu_out_block[sel][chno_t].dirty = 1;
289 gsu_scale_block[sel][chno_t].dirty = 1;
290 gsu_coeff_block[sel][chno_t].dirty = 1;
291
292 return 0;
293 }
294
295 /*****************************************************************************
296 * function : de_gsu_calc_scaler_para(struct de_rect64 crop,
297 * struct de_rect frame,
298 * struct de_rect *crop_fix,
299 * struct scaler_para *para)
300 * description : calculate scaler parameters
301 * parameters :
302 * crop.w <frame buffer crop width with 32bit fraction part>
303 * crop.h <frame buffer crop height with 32bit fraction part>
304 * crop.x <frame buffer coordinate x with 32bit fraction part>
305 * crop.y <frame buffer coordinate y with 32bit fraction part>
306 * frame.w <frame width in integer>
307 * frame.h <frame height in integer>
308 * crop_fix->w <framebuffer crop_fix width after fixed>
309 * crop_fix->h <framebuffer crop_fix height after fixed>
310 * crop_fix->x <framebuffer crop_fix coordinate x after fixed>
311 * crop_fix->y <framebuffer crop_fix coordinate y after fixed>
312 * hstep <horizon scale ratio>
313 * vstep <vertical scale ratio>
314 * hphase <horizon initial phase>
315 * vphase <vertical initial phase>
316 * return :
317 * success
318 */
de_gsu_calc_scaler_para(struct de_rect64 crop,struct de_rect frame,struct de_rect * crop_fix,struct scaler_para * para)319 int de_gsu_calc_scaler_para(struct de_rect64 crop, struct de_rect frame,
320 struct de_rect *crop_fix, struct scaler_para *para)
321 {
322 unsigned long long tmp = 0;
323
324 tmp = (N2_POWER(crop.w, GSU_PHASE_FRAC_BITWIDTH));
325 if (frame.w)
326 tmp = tmp / frame.w;
327 else
328 tmp = 0;
329 para->hstep = (unsigned int)(tmp >> GSU_FB_FRAC_BITWIDTH);
330
331 tmp = (N2_POWER(crop.h, GSU_PHASE_FRAC_BITWIDTH));
332 if (frame.h)
333 tmp = tmp / frame.h;
334 else
335 tmp = 0;
336 para->vstep = (unsigned int)(tmp >> GSU_FB_FRAC_BITWIDTH);
337
338 para->hphase
339 = ((crop.x & 0xffffffff) >> (32 - GSU_PHASE_FRAC_BITWIDTH));
340 para->vphase
341 = ((crop.y & 0xffffffff) >> (32 - GSU_PHASE_FRAC_BITWIDTH));
342
343 crop_fix->w
344 = (unsigned int)(
345 ((crop.w & 0xffffffff) + (crop.x & 0xffffffff)) >=
346 N2_POWER(1, GSU_FB_FRAC_BITWIDTH) ?
347 ((crop.w >> GSU_FB_FRAC_BITWIDTH) + 1)
348 : (crop.w >> GSU_FB_FRAC_BITWIDTH));
349
350 crop_fix->h
351 = (unsigned int)(
352 ((crop.h & 0xffffffff) + (crop.y & 0xffffffff)) >=
353 N2_POWER(1, GSU_FB_FRAC_BITWIDTH) ?
354 ((crop.h >> GSU_FB_FRAC_BITWIDTH) + 1)
355 : (crop.h >> GSU_FB_FRAC_BITWIDTH));
356
357 crop_fix->x = (int)(crop.x >> GSU_FB_FRAC_BITWIDTH);
358 crop_fix->y = (int)(crop.y >> GSU_FB_FRAC_BITWIDTH);
359
360 return 0;
361 }
362
363 /**
364 * function : de_calc_ovl_coord(unsigned int frame_coord,
365 * unsigned int scale_step,
366 * int gsu_sel)
367 * description : calculate overlay coordinate
368 * parameters :
369 * frame_coord <frame buffer coordinate>
370 * scale_step <vsu/gsu horizontal/vertical scale step>
371 * gsu_sel <is gsu or not: 0-is vsu, others-is gsu>
372 * return :
373 * layer_coord <layer coordinate>
374 */
de_calc_ovl_coord(unsigned int frame_coord,unsigned int scale_step,int gsu_sel)375 int de_calc_ovl_coord(unsigned int frame_coord, unsigned int scale_step,
376 int gsu_sel)
377 {
378 int shift, half, layer_coord;
379
380 shift = (gsu_sel == 0) ?
381 VSU_PHASE_FRAC_BITWIDTH : GSU_PHASE_FRAC_BITWIDTH;
382 half = (1 << (shift - 1));
383 layer_coord = (frame_coord * scale_step + half) >> shift;
384 DE_INF("half_shift_xy=<%x,%d,%d>\n", half, shift, layer_coord);
385
386 return layer_coord;
387 }
388
389 /**
390 * function : de_gsu_sel_ovl_scaler_para(unsigned char *en,
391 * struct scaler_para *layer_scale_para[],
392 * struct scaler_para *ovl_scale_para)
393 * description : calculate ui overlay scaler parameters
394 * parameters :
395 * en <pointer of layer enable>
396 * layer_scale_para <pointer array of ui layer scaler parameter>
397 * ovl_scale_para <pointer of ui overlay scaler parameter>
398 * return :
399 * success
400 */
de_gsu_sel_ovl_scaler_para(unsigned char * en,struct scaler_para * layer_scale_para,struct scaler_para * ovl_scale_para)401 int de_gsu_sel_ovl_scaler_para(unsigned char *en,
402 struct scaler_para *layer_scale_para,
403 struct scaler_para *ovl_scale_para)
404 {
405 int i, j, layer_en_num;
406 int used_layer_idx[LAYER_MAX_NUM_PER_CHN];
407
408 /* get valid layer number and record layer index */
409 layer_en_num = 0;
410 j = 0;
411 for (i = 0; i < LAYER_MAX_NUM_PER_CHN; i++) {
412 if (*(en + i) == 1) {
413 layer_en_num++;
414 used_layer_idx[j++] = i;
415 }
416 }
417
418 /* only one layer enabled in one overlay */
419 if (layer_en_num == 1) {
420 /* set overlay scale para through this layer */
421 ovl_scale_para->hphase
422 = layer_scale_para[used_layer_idx[0]].hphase;
423 ovl_scale_para->vphase
424 = layer_scale_para[used_layer_idx[0]].vphase;
425 ovl_scale_para->hstep
426 = layer_scale_para[used_layer_idx[0]].hstep;
427 ovl_scale_para->vstep
428 = layer_scale_para[used_layer_idx[0]].vstep;
429 } else if (layer_en_num > 1) {
430 /* two or more layers enabled in one overlay */
431 /* set overlay scale step through first enabled layer */
432 ovl_scale_para->hstep
433 = layer_scale_para[used_layer_idx[0]].hstep;
434 ovl_scale_para->vstep
435 = layer_scale_para[used_layer_idx[0]].vstep;
436
437 /* set overlay phase through 1st enabled non-zero-phase layer */
438 for (i = 0; i < layer_en_num; i++) {
439 if (layer_scale_para[used_layer_idx[i]].hphase != 0) {
440 ovl_scale_para->hphase
441 = layer_scale_para[used_layer_idx[i]].hphase;
442 break;
443 }
444 }
445
446 /* all layer phase equal to zero */
447 if (i == layer_en_num) {
448 ovl_scale_para->hphase
449 = layer_scale_para[used_layer_idx[0]].hphase;
450 }
451
452 /* set overlay phase through 1st enabled non-zero-phase layer */
453 for (i = 0; i < layer_en_num; i++) {
454 if (layer_scale_para[used_layer_idx[i]].vphase != 0) {
455 ovl_scale_para->vphase
456 = layer_scale_para[used_layer_idx[i]].vphase;
457 break;
458 }
459 }
460
461 /* all layer phase equal to zero */
462 if (i == layer_en_num) {
463 ovl_scale_para->vphase
464 = layer_scale_para[used_layer_idx[0]].vphase;
465 }
466
467 } else {
468 ovl_scale_para->hphase = 0;
469 ovl_scale_para->vphase = 0;
470 ovl_scale_para->hstep
471 = (unsigned int)N2_POWER(1, GSU_PHASE_FRAC_BITWIDTH);
472 ovl_scale_para->vstep
473 = (unsigned int)N2_POWER(1, GSU_PHASE_FRAC_BITWIDTH);
474 }
475
476 return 0;
477 }
478