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_lti.c
15  *
16  *  Description :       display engine 2.0 LTI basic function definition
17  *
18  *  History     :       2014/04/01  vito cheng  v0.1  Initial version
19  *
20  ******************************************************************************/
21 
22 #ifdef CONFIG_DISP2_SUNXI_SUPPORT_ENAHNCE
23 #include "de_lti_type.h"
24 #include "de_enhance.h"
25 
26 static volatile struct __lti_reg_t *lti_dev[DE_NUM][CHN_NUM];
27 static struct de_reg_blocks lti_block[DE_NUM][CHN_NUM];
28 
29 /*******************************************************************************
30  * function       : de_lti_set_reg_base(unsigned int sel, unsigned int chno,
31  *                    unsigned int base)
32  * description    : set lti reg base
33  * parameters     :
34  *                  sel         <rtmx select>
35  *                  chno        <overlay select>
36  *                  base        <reg base>
37  * return         :
38  *                  success
39  ******************************************************************************/
de_lti_set_reg_base(unsigned int sel,unsigned int chno,void * base)40 int de_lti_set_reg_base(unsigned int sel, unsigned int chno, void *base)
41 {
42     lti_dev[sel][chno] = (struct __lti_reg_t *) base;
43 
44     return 0;
45 }
46 
de_lti_update_regs(unsigned int sel,unsigned int chno)47 int de_lti_update_regs(unsigned int sel, unsigned int chno)
48 {
49     if (lti_block[sel][chno].dirty == 0x1) {
50         regwrite((void *)lti_block[sel][chno].off,
51                lti_block[sel][chno].val, lti_block[sel][chno].size);
52         lti_block[sel][chno].dirty = 0x0;
53     }
54 
55     return 0;
56 }
57 
de_lti_init(unsigned int sel,unsigned int chno,uintptr_t reg_base)58 int de_lti_init(unsigned int sel, unsigned int chno, uintptr_t reg_base)
59 {
60     uintptr_t base;
61     void *memory;
62 
63     /* FIXME  display path offset should be defined */
64     base = reg_base + (sel + 1) * 0x00100000 + LTI_OFST;
65 #if defined(CONFIG_ARCH_SUN50IW10)
66     if (sel)
67         base = base - 0x00100000;
68 #endif
69     DE_INF("sel %d, lti_base[%d]=0x%p\n", sel, chno, (void *)base);
70 
71     memory = disp_sys_malloc(sizeof(struct __lti_reg_t));
72     if (memory == NULL) {
73         DE_WRN("disp_sys_malloc lti[%d][%d] memory fail! size=0x%x\n", sel, chno,
74               (unsigned int)sizeof(struct __lti_reg_t));
75         return -1;
76     }
77 
78     lti_block[sel][chno].off = base;
79     lti_block[sel][chno].val = memory;
80     lti_block[sel][chno].size = 0x40;
81     lti_block[sel][chno].dirty = 0;
82 
83     de_lti_set_reg_base(sel, chno, memory);
84 
85     return 0;
86 }
87 
de_lti_exit(unsigned int sel,unsigned int chno)88 int de_lti_exit(unsigned int sel, unsigned int chno)
89 {
90     disp_sys_free(lti_block[sel][chno].val);
91 
92     return 0;
93 }
94 
95 /*******************************************************************************
96  * function       : de_lti_enable(unsigned int sel, unsigned int chno,
97  *                  unsigned int en)
98  * description    : enable/disable lti
99  * parameters     :
100  *                  sel         <rtmx select>
101  *                  chno        <overlay select>
102  *                  en          <enable: 0-disable; 1-enable>
103  * return         :
104  *                  success
105  ******************************************************************************/
de_lti_enable(unsigned int sel,unsigned int chno,unsigned int en)106 int de_lti_enable(unsigned int sel, unsigned int chno, unsigned int en)
107 {
108     lti_dev[sel][chno]->ctrl.bits.en = en;
109     lti_block[sel][chno].dirty = 1;
110     return 0;
111 }
112 
113 /*******************************************************************************
114  * function       : de_lti_set_size(unsigned int sel, unsigned int chno,
115  *                    unsigned int width, unsigned int height)
116  * description    : set lti size
117  * parameters     :
118  *                  sel         <rtmx select>
119  *                  chno        <overlay select>
120  *                  width       <input width>
121  *                                      height  <input height>
122  * return         :
123  *                  success
124 ******************************************************************************/
de_lti_set_size(unsigned int sel,unsigned int chno,unsigned int width,unsigned int height)125 int de_lti_set_size(unsigned int sel, unsigned int chno, unsigned int width,
126             unsigned int height)
127 {
128     lti_dev[sel][chno]->size.bits.width = width - 1;
129     lti_dev[sel][chno]->size.bits.height = height - 1;
130     lti_block[sel][chno].dirty = 1;
131     return 0;
132 }
133 
134 /*******************************************************************************
135  * function       : de_lti_set_window(unsigned int sel, unsigned int chno,
136  *                   unsigned int win_enable, struct de_rect window)
137  * description    : set lti window
138  * parameters     :
139  *                  sel         <rtmx select>
140  *                  chno        <overlay select>
141  *                  win_enable  <enable: 0-window mode disable;
142  *                                       1-window mode enable>
143  *                  window  <window rectangle>
144  * return         :
145  *                  success
146  ******************************************************************************/
de_lti_set_window(unsigned int sel,unsigned int chno,unsigned int win_enable,struct de_rect window)147 int de_lti_set_window(unsigned int sel, unsigned int chno,
148               unsigned int win_enable, struct de_rect window)
149 {
150     lti_dev[sel][chno]->ctrl.bits.win_en = win_enable;
151 
152     if (win_enable) {
153         lti_dev[sel][chno]->win0.bits.win_left = window.x;
154         lti_dev[sel][chno]->win0.bits.win_top = window.y;
155         lti_dev[sel][chno]->win1.bits.win_right =
156             window.x + window.w - 1;
157         lti_dev[sel][chno]->win1.bits.win_bot = window.y + window.h - 1;
158     }
159     lti_block[sel][chno].dirty = 1;
160     return 0;
161 }
162 
163 /*******************************************************************************
164  * function       : de_lti_set_para(unsigned int sel, unsigned int chno,
165  *                    unsigned int gain)
166  * description    : set lti para
167  * parameters     :
168  *                  sel         <rtmx select>
169  *                  chno        <overlay select>
170  *                  gain        <lti gain: normal setting 0-3>
171  * return         :
172  *                  success
173  ******************************************************************************/
de_lti_set_para(unsigned int sel,unsigned int chno,unsigned int gain)174 int de_lti_set_para(unsigned int sel, unsigned int chno, unsigned int gain)
175 {
176     lti_dev[sel][chno]->gain.bits.lti_fil_gain = gain;
177 
178     lti_dev[sel][chno]->ctrl.bits.sel = 0;
179     lti_dev[sel][chno]->ctrl.bits.nonl_en = 0;
180 
181     lti_dev[sel][chno]->coef0.bits.c0 = 127;
182     lti_dev[sel][chno]->coef0.bits.c1 = 64;
183     lti_dev[sel][chno]->coef1.bits.c2 = 0xe0;
184     lti_dev[sel][chno]->coef1.bits.c3 = 0xc0;
185     lti_dev[sel][chno]->coef2.bits.c4 = 0xe0;
186 
187     lti_dev[sel][chno]->corth.bits.lti_cor_th = 4;
188     lti_dev[sel][chno]->diff.bits.offset = 32;
189     lti_dev[sel][chno]->diff.bits.slope = 4;
190     lti_dev[sel][chno]->edge_gain.bits.edge_gain = 1;
191     lti_dev[sel][chno]->os_con.bits.core_x = 0;
192     lti_dev[sel][chno]->os_con.bits.clip = 40;
193     lti_dev[sel][chno]->os_con.bits.peak_limit = 1;
194 
195     lti_dev[sel][chno]->win_range.bits.win_range = 2;
196     lti_dev[sel][chno]->elvel_th.bits.elvel_th = 32;
197 
198     lti_block[sel][chno].dirty = 1;
199     return 0;
200 }
201 
202 /*******************************************************************************
203  * function       : de_lti_info2para(unsigned int sharp, struct de_rect window,
204  *                   struct __lti_config_data *para)
205  * description    : info->para conversion
206  * parameters     :
207  *                  sharp               <gain info from user>
208  *                  window              <window info>
209  *                  para                <bsp para>
210  * return         :
211  *                  success
212  ******************************************************************************/
de_lti_info2para(unsigned int sharp,struct de_rect window,struct __lti_config_data * para)213 int de_lti_info2para(unsigned int sharp, struct de_rect window,
214              struct __lti_config_data *para)
215 {
216     int mode;
217     int lti_para[LTI_PARA_NUM][LTI_MODE_NUM] = {
218         {0, 3},     /* gain */
219     };
220 
221     /* parameters */
222     mode = sharp & 0xf;
223     para->lti_en = mode ? 1 : 0;
224     para->gain = lti_para[0][mode];
225 
226     return 0;
227 }
228 #endif
229