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