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_fcc.c
15  *
16  *  Description :       display engine 2.0 fcc base functions implement
17  *
18  *  History     :       2014/03/28  iptang  v0.1  Initial version
19  *
20  ******************************************************************************/
21 
22 #ifdef CONFIG_DISP2_SUNXI_SUPPORT_ENAHNCE
23 #include "de_fcc_type.h"
24 #include "de_rtmx.h"
25 #include "de_vep_table.h"
26 #include "de_enhance.h"
27 
28 static volatile struct __fcc_reg_t *fcc_dev[DE_NUM][CHN_NUM];
29 static struct de_reg_blocks fcc_para_block[DE_NUM][CHN_NUM];
30 
31 /*******************************************************************************
32  *  function       : de_fcc_set_reg_base
33  *  description    : set fcc reg base
34  *  parameters     :
35  *                   sel         <rtmx select>
36  *                   chno        <overlay select>
37  *                   base        <reg base>
38  *  return         :
39  *                   success
40  ******************************************************************************/
de_fcc_set_reg_base(unsigned int sel,unsigned int chno,void * base)41 int de_fcc_set_reg_base(unsigned int sel, unsigned int chno, void *base)
42 {
43     fcc_dev[sel][chno] = (struct __fcc_reg_t *) base;
44 
45     return 0;
46 }
47 
de_fcc_init(unsigned int sel,unsigned int chno,uintptr_t reg_base)48 int de_fcc_init(unsigned int sel, unsigned int chno, uintptr_t reg_base)
49 {
50     uintptr_t fcc_base;
51     void *memory;
52 
53     fcc_base = reg_base + (sel + 1) * 0x00100000 + FCC_OFST;
54 #if defined(CONFIG_ARCH_SUN50IW10)
55     if (sel)
56         fcc_base = fcc_base - 0x00100000;
57 #endif
58     /* FIXME  display path offset should be defined */
59 
60     memory = disp_sys_malloc(sizeof(struct __fcc_reg_t));
61     if (memory == NULL) {
62         DE_WRN("disp_sys_malloc vep fcc[%d][%d] memory fail! size=0x%x\n", sel,
63               chno, (unsigned int)sizeof(struct __fcc_reg_t));
64         return -1;
65     }
66 
67     fcc_para_block[sel][chno].off = fcc_base;
68     fcc_para_block[sel][chno].val = memory;
69     fcc_para_block[sel][chno].size = 0x48;
70     fcc_para_block[sel][chno].dirty = 0;
71 
72     de_fcc_set_reg_base(sel, chno, memory);
73 
74     return 0;
75 }
76 
de_fcc_exit(unsigned int sel,unsigned int chno)77 int de_fcc_exit(unsigned int sel, unsigned int chno)
78 {
79     disp_sys_free(fcc_para_block[sel][chno].val);
80 
81     return 0;
82 }
83 
de_fcc_update_regs(unsigned int sel,unsigned int chno)84 int de_fcc_update_regs(unsigned int sel, unsigned int chno)
85 {
86     if (fcc_para_block[sel][chno].dirty == 0x1) {
87         regwrite((void *)fcc_para_block[sel][chno].off,
88                fcc_para_block[sel][chno].val,
89                fcc_para_block[sel][chno].size);
90         fcc_para_block[sel][chno].dirty = 0x0;
91     }
92 
93     return 0;
94 }
95 
96 /*******************************************************************************
97  * function       : de_fcc_enable(unsigned int sel, unsigned int chno,
98  *                   unsigned int en)
99  * description    : enable/disable fcc
100  * parameters     :
101  *                  sel         <rtmx select>
102  *                  chno        <overlay select>
103  *                  en          <enable: 0-disable; 1-enable>
104  * return         :
105  *                  success
106  ******************************************************************************/
de_fcc_enable(unsigned int sel,unsigned int chno,unsigned int en)107 int de_fcc_enable(unsigned int sel, unsigned int chno, unsigned int en)
108 {
109     fcc_dev[sel][chno]->fcc_ctl.bits.en = en;
110     fcc_para_block[sel][chno].dirty = 1;
111 
112     return 0;
113 }
114 
115 /*******************************************************************************
116  * function       : de_fcc_set_size(unsigned int sel, unsigned int chno,
117  *                  unsigned int width, unsigned int height)
118  * description    : set fcc size
119  * parameters     :
120  *                  sel         <rtmx select>
121  *                  chno        <overlay select>
122  *                  width       <input width>
123  *                                      height  <input height>
124  * return         :
125  *                  success
126  ******************************************************************************/
de_fcc_set_size(unsigned int sel,unsigned int chno,unsigned int width,unsigned int height)127 int de_fcc_set_size(unsigned int sel, unsigned int chno, unsigned int width,
128             unsigned int height)
129 {
130     fcc_dev[sel][chno]->fcc_size.bits.width = width == 0 ? 0 : width - 1;
131     fcc_dev[sel][chno]->fcc_size.bits.height = height == 0 ? 0 : height - 1;
132 
133     fcc_para_block[sel][chno].dirty = 1;
134 
135     return 0;
136 }
137 
138 /*******************************************************************************
139  * function       : de_fcc_set_window(unsigned int sel, unsigned int chno,
140  *                    unsigned int win_en, struct de_rect window)
141  * description    : set fcc window
142  * parameters     :
143  *                  sel         <rtmx select>
144  *                  chno        <overlay select>
145  *                  win_en      <enable: 0-window mode disable;
146  *                                       1-window mode enable>
147  *                  window  <window rectangle>
148  * return         :
149  *                  success
150  ******************************************************************************/
de_fcc_set_window(unsigned int sel,unsigned int chno,unsigned int win_en,struct de_rect window)151 int de_fcc_set_window(unsigned int sel, unsigned int chno, unsigned int win_en,
152               struct de_rect window)
153 {
154     fcc_dev[sel][chno]->fcc_ctl.bits.win_en = win_en & 0x1;
155 
156     if (win_en) {
157         fcc_dev[sel][chno]->fcc_win0.bits.left = window.x;
158         fcc_dev[sel][chno]->fcc_win0.bits.top = window.y;
159         fcc_dev[sel][chno]->fcc_win1.bits.right =
160             window.x + window.w - 1;
161         fcc_dev[sel][chno]->fcc_win1.bits.bot = window.y + window.h - 1;
162     }
163 
164     fcc_para_block[sel][chno].dirty = 1;
165 
166     return 0;
167 }
168 
169 /*******************************************************************************
170  * function       : de_fcc_set_para(unsigned int sel, unsigned int chno,
171  *                   unsigned int mode)
172  * description    : set fcc para
173  * parameters     :
174  *                  sel         <rtmx select>
175  *                  chno        <overlay select>
176  *                  sgain
177  * return         :
178  *                  success
179  ******************************************************************************/
de_fcc_set_para(unsigned int sel,unsigned int chno,unsigned int sgain[6])180 int de_fcc_set_para(unsigned int sel, unsigned int chno, unsigned int sgain[6])
181 {
182     regwrite((void *)fcc_dev[sel][chno]->fcc_range,
183            (void *)&fcc_range_gain[0], sizeof(int) * 6);
184     regwrite((void *)fcc_dev[sel][chno]->fcc_gain, (void *)&sgain[0],
185            sizeof(int) * 6);
186 
187     fcc_para_block[sel][chno].dirty = 1;
188 
189     return 0;
190 }
191 
192 /*******************************************************************************
193  * function       : de_fcc_info2para(unsigned int gain, struct de_rect window,
194  *                    struct __fcc_config_data *para)
195  * description    : info->para conversion
196  * parameters     :
197  *                  gain                <gain info from user>
198  *                  window              <window info>
199  *                  para                <bsp para>
200  * return         :
201  *                  success
202  ******************************************************************************/
de_fcc_info2para(unsigned int sgain0,unsigned int sgain1,unsigned int sgain2,unsigned int sgain3,unsigned int sgain4,unsigned int sgain5,struct de_rect window,struct __fcc_config_data * para)203 int de_fcc_info2para(unsigned int sgain0, unsigned int sgain1,
204             unsigned int sgain2, unsigned int sgain3,
205             unsigned int sgain4, unsigned int sgain5,
206             struct de_rect window, struct __fcc_config_data *para)
207 {
208     int fcc_para[FCC_PARA_NUM][FCC_MODE_NUM] = {
209         {0, 5, 10},   /* sgain0 */
210         {0, 12, 24},    /* sgain1 */
211         {0, 4, 8},    /* sgain2 */
212         {0, 0, 0},    /* sgain3 */
213         {0, 0, 0},    /* sgain4 */
214         {0, 0, 0},    /* sgain5 */
215     };
216 
217     /* parameters */
218     para->fcc_en =
219         ((sgain0 | sgain1 | sgain2 | sgain3 | sgain4 | sgain5) == 0) ?
220             0 : 1;
221 
222     para->sgain[0] = fcc_para[0][sgain0];
223     para->sgain[1] = fcc_para[1][sgain1];
224     para->sgain[2] = fcc_para[2][sgain2];
225     para->sgain[3] = fcc_para[3][sgain3];
226     para->sgain[4] = fcc_para[4][sgain4];
227     para->sgain[5] = fcc_para[5][sgain5];
228 
229     return 0;
230 }
231 #endif
232