1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author           Notes
8  * 2011-08-09     lgnq         first version for LS1B DC
9  * 2015-07-06    chinesebear   modified for loongson 1c
10  * 2018-01-06    sundm75       modified for smartloong
11  */
12  #include <rtthread.h>
13 
14 #include "display_controller.h"
15 #include "../../libraries/ls1c_pwm.h"
16 #include "../../libraries/ls1c_public.h"
17 #include "../../libraries/ls1c_gpio.h"
18 #include "../../libraries/ls1c_pin.h"
19 
20 #if (defined PKG_USING_GUIENGINE) || (defined RT_USING_RTGUI)
21 struct vga_struct vga_mode[] =
22 {
23     {/*"480x272_60.00"*/    111000,   480,    482,    523,    525,    272,    274,    284,    286,    },
24     {/*"640x480_70.00"*/    28560,  640,    664,    728,    816,    480,    481,    484,    500,    },
25     {/*"640x640_60.00"*/    33100,    640,    672,    736,    832,    640,    641,    644,    663,    },
26     {/*"640x768_60.00"*/    39690,    640,    672,    736,    832,    768,    769,    772,    795,    },
27     {/*"640x800_60.00"*/    42130,    640,    680,    744,    848,    800,    801,    804,    828,    },
28     {/*"800x480_70.00"*/    35840,  800,    832,    912,    1024,   480,    481,    484,    500,    },
29     {/*"800x600_60.00"*/    38220,    800,    832,    912,    1024,    600,    601,    604,    622,    },
30     {/*"800x640_60.00"*/    40730,    800,    832,    912,    1024,    640,    641,    644,    663,    },
31     {/*"832x600_60.00"*/    40010,    832,    864,    952,    1072,    600,    601,    604,    622,    },
32     {/*"832x608_60.00"*/    40520,    832,    864,    952,    1072,    608,    609,    612,    630,    },
33     {/*"1024x480_60.00"*/    38170,    1024,    1048,    1152,    1280,    480,    481,    484,    497,    },
34     {/*"1024x600_60.00"*/    48960,    1024,    1064,    1168,    1312,    600,    601,    604,    622,    },
35     {/*"1024x640_60.00"*/    52830,    1024,    1072,    1176,    1328,    640,    641,    644,    663,    },
36     {/*"1024x768_60.00"*/    64110,    1024,    1080,    1184,    1344,    768,    769,    772,    795,    },
37     {/*"1152x764_60.00"*/   71380,  1152,   1208,   1328,   1504,   764,    765,    768,    791,    },
38     {/*"1280x800_60.00"*/   83460,  1280,   1344,   1480,   1680,   800,    801,    804,    828,    },
39     {/*"1280x1024_55.00"*/  98600,  1280,   1352,   1488,   1696,   1024,   1025,   1028,   1057,   },
40     {/*"1440x800_60.00"*/   93800,  1440,   1512,   1664,   1888,   800,    801,    804,    828,    },
41     {/*"1440x900_67.00"*/   120280, 1440,   1528,   1680,   1920,   900,    901,    904,    935,    },
42 };
43 
44 static volatile int fb_index = 0;
45 
46 rt_align(16)
47 volatile rt_uint16_t _rt_framebuffer[FB_YSIZE][FB_XSIZE];
48 volatile rt_uint16_t _rt_framebuffer0[FB_YSIZE][FB_XSIZE];
49 volatile rt_uint16_t _rt_framebuffer1[FB_YSIZE][FB_XSIZE];
50 static struct rt_device_graphic_info _dc_info;
51 
pwminit(void)52 static void pwminit(void)
53 {
54     pwm_info_t pwm_info;
55     pwm_info.gpio = LS1C_PWM0_GPIO06;           // pwm引脚位gpio06
56     pwm_info.mode = PWM_MODE_NORMAL;            // 正常模式--连续输出pwm波形
57     pwm_info.duty = 0.85;                       // pwm占空比 85%
58     pwm_info.period_ns = 5*1000*1000;            // pwm周期5ms
59 
60     /*pwm初始化,初始化后立即产生pwm波形*/
61     pwm_init(&pwm_info);
62 
63     /* 使能pwm */
64     pwm_enable(&pwm_info);
65 }
caclulate_freq(rt_uint32_t XIN,rt_uint32_t PCLK)66 int caclulate_freq(rt_uint32_t  XIN, rt_uint32_t PCLK)
67 {
68     rt_uint32_t divider_int;
69     rt_uint32_t needed_pixclk;
70     rt_uint32_t  pll_clk, pix_div;
71     rt_uint32_t  regval;
72 
73 
74     pll_clk = PLL_FREQ; // 读CPU的 PLL及SDRAM 分频系数
75     pll_clk =( pll_clk>>8 )& 0xff;
76     pll_clk = XIN *  pll_clk / 4 ;
77     pix_div = PLL_DIV_PARAM;//读CPU的 CPU/CAMERA/DC 分频系数
78     pix_div = (pix_div>>24)&0xff;
79     rt_kprintf("old pll_clk=%d, pix_div=%d\n", pll_clk, pix_div);
80 
81     divider_int = pll_clk/(1000000) *PCLK/1000;
82     if(divider_int%1000>=500)
83         divider_int = divider_int/1000+1;
84     else
85         divider_int = divider_int/1000;
86     rt_kprintf("divider_int = %d\n", divider_int);
87 
88     /* check whether divisor is too small. */
89     if (divider_int < 1) {
90         rt_kprintf("Warning: clock source is too slow.Try smaller resolution\n");
91         divider_int = 1;
92     }
93     else if(divider_int > 100) {
94         rt_kprintf("Warning: clock source is too fast.Try smaller resolution\n");
95         divider_int = 100;
96     }
97     /* 配置分频寄存器 */
98     {
99         rt_uint32_t regval = 0;
100         regval = PLL_DIV_PARAM;
101         /*首先需要把分频使能位清零 */
102         regval &= ~0x80000030;    //PIX_DIV_VALID  PIX_SEL  置0
103         regval &= ~(0x3f<<24);    //PIX_DIV 清零
104         regval |= divider_int << 24;
105         PLL_DIV_PARAM = regval;
106         regval |= 0x80000030;    //PIX_DIV_VALID  PIX_SEL  置1
107         PLL_DIV_PARAM = regval;
108     }
109     rt_kprintf("new PLL_FREQ=0x%x, PLL_DIV_PARAM=0x%x\n", PLL_FREQ, PLL_DIV_PARAM);
110     rt_thread_delay(10);
111     return 0;
112 }
113 
rt_dc_init(rt_device_t dev)114 static rt_err_t rt_dc_init(rt_device_t dev)
115 {
116     int i, out, mode=-1;
117     int val;
118 
119     rt_kprintf("PWM initied\n");
120     /* Set the back light PWM. */
121     pwminit();
122 
123     for (i=0; i<sizeof(vga_mode)/sizeof(struct vga_struct); i++)
124     {
125         if (vga_mode[i].hr == FB_XSIZE && vga_mode[i].vr == FB_YSIZE)
126         {
127             mode=i;
128             /* 计算时钟 配置频率*/
129             caclulate_freq(OSC, vga_mode[i].pclk);
130             break;
131         }
132     }
133 
134     if (mode<0)
135     {
136         rt_kprintf("\n\n\nunsupported framebuffer resolution\n\n\n");
137         return -RT_ERROR;
138     }
139 
140     DC_FB_CONFIG = 0x0;
141     DC_FB_CONFIG = 0x3; //    // framebuffer configuration RGB565
142     DC_DITHER_CONFIG = 0x0;  //颜色抖动配置寄存器
143     DC_DITHER_TABLE_LOW = 0x0; //颜色抖动查找表低位寄存器
144     DC_DITHER_TABLE_HIGH = 0x0; //颜色抖动查找表高位寄存器
145     DC_PANEL_CONFIG = 0x80001311; //液晶面板配置寄存器
146     DC_PANEL_TIMING = 0x0;
147 
148     DC_HDISPLAY = (vga_mode[mode].hfl<<16) | vga_mode[mode].hr;
149     DC_HSYNC = 0x40000000 | (vga_mode[mode].hse<<16) | vga_mode[mode].hss;
150     DC_VDISPLAY = (vga_mode[mode].vfl<<16) | vga_mode[mode].vr;
151     DC_VSYNC = 0x40000000 | (vga_mode[mode].vse<<16) | vga_mode[mode].vss;
152 
153 #if defined(CONFIG_VIDEO_32BPP)
154     DC_FB_CONFIG = 0x00100105;
155     DC_FB_BUFFER_STRIDE = FB_XSIZE*4;
156 #elif defined(CONFIG_VIDEO_24BPP)
157     DC_FB_CONFIG = 0x00100104;
158     DC_FB_BUFFER_STRIDE = (FB_XSIZE*4+255)&(~255);
159 #elif defined(CONFIG_VIDEO_16BPP)// 使用这个选项
160     DC_FB_CONFIG = 0x00100103;
161     DC_FB_BUFFER_STRIDE = (FB_XSIZE*2+0x7f)&(~0x7f);
162 #elif defined(CONFIG_VIDEO_15BPP)
163     DC_FB_CONFIG = 0x00100102;
164     DC_FB_BUFFER_STRIDE =  (FB_XSIZE*2+255)&(~255);
165 #elif defined(CONFIG_VIDEO_12BPP)
166     DC_FB_CONFIG = 0x00100101;
167     DC_FB_BUFFER_STRIDE =  (FB_XSIZE*2+255)&(~255);
168 #else
169     DC_FB_CONFIG = 0x00100104;
170     DC_FB_BUFFER_STRIDE = (FB_XSIZE*4+255)&(~255);
171 #endif
172     return RT_EOK;
173 }
174 
rt_dc_control(rt_device_t dev,int cmd,void * args)175 static rt_err_t rt_dc_control(rt_device_t dev, int cmd, void *args)
176 {
177     switch (cmd)
178     {
179     case RTGRAPHIC_CTRL_RECT_UPDATE:
180     {
181         if (fb_index == 0)
182         {
183             DC_FB_BUFFER_ADDR0 = (rt_uint32_t)_rt_framebuffer1 - 0x80000000;
184             DC_FB_BUFFER_ADDR1 = (rt_uint32_t)_rt_framebuffer1 - 0x80000000;
185             rt_memcpy((void *)_rt_framebuffer1, (const void *)_rt_framebuffer, sizeof(_rt_framebuffer));
186             rt_memcpy((void *)_rt_framebuffer1, (const void *)_rt_framebuffer, sizeof(_rt_framebuffer));
187             fb_index =1;
188         }
189         else
190         {
191             DC_FB_BUFFER_ADDR0 = (rt_uint32_t)_rt_framebuffer0 - 0x80000000;
192             DC_FB_BUFFER_ADDR1 = (rt_uint32_t)_rt_framebuffer0 - 0x80000000;
193             rt_memcpy((void *)_rt_framebuffer0, (const void *)_rt_framebuffer, sizeof(_rt_framebuffer));
194             rt_memcpy((void *)_rt_framebuffer0, (const void *)_rt_framebuffer, sizeof(_rt_framebuffer));
195             fb_index =0;
196         }
197         break;
198     }
199     case RTGRAPHIC_CTRL_POWERON:
200         break;
201     case RTGRAPHIC_CTRL_POWEROFF:
202         break;
203     case RTGRAPHIC_CTRL_GET_INFO:
204         rt_memcpy(args, &_dc_info, sizeof(_dc_info));
205         break;
206     case RTGRAPHIC_CTRL_SET_MODE:
207         break;
208     }
209 
210     return RT_EOK;
211 }
212 
rt_hw_dc_init(void)213 void rt_hw_dc_init(void)
214 {
215     rt_device_t dc = rt_malloc(sizeof(struct rt_device));
216     if (dc == RT_NULL)
217     {
218         rt_kprintf("dc == RT_NULL\n");
219         return; /* no memory yet */
220     }
221 
222     _dc_info.bits_per_pixel = 16;
223     _dc_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565;
224     _dc_info.framebuffer = (rt_uint8_t*)HW_FB_ADDR;
225     _dc_info.width = FB_XSIZE;
226     _dc_info.height = FB_YSIZE;
227 
228     /* init device structure */
229     dc->type = RT_Device_Class_Graphic;
230     dc->init = rt_dc_init;
231     dc->open = RT_NULL;
232     dc->close = RT_NULL;
233     dc->control = rt_dc_control;
234     dc->user_data = (void*)&_dc_info;
235 
236     /* register Display Controller device to RT-Thread */
237     rt_device_register(dc, "dc", RT_DEVICE_FLAG_RDWR);
238 
239     rt_device_init(dc);
240 }
241 
242 #include <rtgui/driver.h>
243 #include "display_controller.h"
244 
245 /* initialize for gui driver */
rtgui_lcd_init(void)246 int rtgui_lcd_init(void)
247 {
248     rt_device_t dc;
249     rt_kprintf("DC initied\n");
250 
251     pin_set_purpose(76, PIN_PURPOSE_OTHER);
252     pin_set_remap(76, PIN_REMAP_DEFAULT);
253 
254      /* init Display Controller */
255     rt_hw_dc_init();
256 
257     /* find Display Controller device */
258     dc = rt_device_find("dc");
259 
260     /* set Display Controller device as rtgui graphic driver */
261     rtgui_graphic_set_device(dc);
262 
263     return 0;
264 }
265 
266 INIT_DEVICE_EXPORT(rtgui_lcd_init);
267 
268 #endif
269