2 * Copyright (C) 2012 Spreadtrum Communications Inc.
\r
8 #include <asm/arch/sprd_lcd.h>
\r
9 #include <asm/arch/dispc_reg.h>
\r
13 //#define CONFIG_FB_NO_FMARK /*Jessica for FPGA*/
\r
15 static int32_t dispc_mcu_send_cmd(uint32_t cmd)
\r
18 /* busy wait for ahb fifo full sign's disappearance */
\r
19 while(dispc_read(DISPC_DBI_QUEUE) & (1<<5)){
\r
20 if(0x0 == ++i%10000){
\r
21 printf("sprdfb: [%s] warning: busy waiting!\n", __FUNCTION__);
\r
25 dispc_write(cmd, DISPC_DBI_CMD);
\r
30 static int32_t dispc_mcu_send_cmd_data(uint32_t cmd, uint32_t data)
\r
33 /* busy wait for ahb fifo full sign's disappearance */
\r
34 while(dispc_read(DISPC_DBI_QUEUE) & (1<<5)){
\r
35 if(0x0 == ++i%10000){
\r
36 printf("sprdfb: [%s] warning: busy waiting!\n", __FUNCTION__);
\r
40 dispc_write(cmd, DISPC_DBI_CMD);
\r
43 /* busy wait for ahb fifo full sign's disappearance */
\r
44 while(dispc_read(DISPC_DBI_QUEUE) & (1<<5)){
\r
45 if(0x0 == ++i%10000){
\r
46 printf("sprdfb: [%s] warning: busy waiting!\n", __FUNCTION__);
\r
50 dispc_write(data, DISPC_DBI_DATA);
\r
55 static int32_t dispc_mcu_send_data(uint32_t data)
\r
58 /* busy wait for ahb fifo full sign's disappearance */
\r
59 while(dispc_read(DISPC_DBI_QUEUE) & (1<<5)){
\r
60 if(0x0 == ++i%10000){
\r
61 printf("sprdfb: [%s] warning: busy waiting!\n", __FUNCTION__);
\r
65 dispc_write(data, DISPC_DBI_DATA);
\r
70 static uint32_t dispc_mcu_read_data(void)
\r
73 /* busy wait for ahb fifo full sign's disappearance */
\r
74 while(dispc_read(DISPC_DBI_QUEUE) & (1<<5)){
\r
75 if(0x0 == ++i%10000){
\r
76 printf("sprdfb: [%s] warning: busy waiting!\n", __FUNCTION__);
\r
79 dispc_write(1 << 24, DISPC_DBI_DATA);
\r
81 return dispc_read(DISPC_DBI_RDATA);
\r
84 static struct ops_mcu dispc_mcu_ops = {
\r
85 .send_cmd = dispc_mcu_send_cmd,
\r
86 .send_cmd_data = dispc_mcu_send_cmd_data,
\r
87 .send_data = dispc_mcu_send_data,
\r
88 .read_data = dispc_mcu_read_data,
\r
92 static uint32_t mcu_calc_timing(struct timing_mcu *timing)
\r
95 uint32_t rcss, rlpw, rhpw, wcss, wlpw, whpw;
\r
96 // struct clk * clk = NULL;
\r
99 FB_PRINT("sprdfb: [%s]: Invalid Param\n", __FUNCTION__);
\r
103 // clk_get(NULL,"clk_dispc_dbi");
\r
104 // clk_rate = clk_get_rate(clk) / 1000000;
\r
105 clk_rate = 250; // 250 MHz
\r
107 FB_PRINT("sprdfb: [%s] clk_rate: 0x%x\n", __FUNCTION__, clk_rate);
\r
109 /********************************************************
\r
110 * we assume : t = ? ns, dispc_dbi = ? MHz so
\r
111 * 1ns need cycle : dispc_dbi /1000
\r
112 * tns need cycles : t * dispc_dbi / 1000
\r
114 ********************************************************/
\r
115 #define MAX_DBI_RWCSS_TIMING_VALUE 15
\r
116 #define MAX_DBI_RWLPW_TIMING_VALUE 63
\r
117 #define MAX_DBI_RWHPW_TIMING_VALUE 63
\r
118 #define DBI_CYCLES(ns) (( (ns) * clk_rate + 1000 - 1)/ 1000)
\r
121 rcss = DBI_CYCLES(timing->rcss);
\r
122 if (rcss > MAX_DBI_RWCSS_TIMING_VALUE) {
\r
123 rcss = MAX_DBI_RWCSS_TIMING_VALUE ;
\r
126 rlpw = DBI_CYCLES(timing->rlpw);
\r
127 if (rlpw > MAX_DBI_RWLPW_TIMING_VALUE) {
\r
128 rlpw = MAX_DBI_RWLPW_TIMING_VALUE ;
\r
131 rhpw = DBI_CYCLES (timing->rhpw);
\r
132 if (rhpw > MAX_DBI_RWHPW_TIMING_VALUE) {
\r
133 rhpw = MAX_DBI_RWHPW_TIMING_VALUE ;
\r
136 wcss = DBI_CYCLES(timing->wcss);
\r
137 if (wcss > MAX_DBI_RWCSS_TIMING_VALUE) {
\r
138 wcss = MAX_DBI_RWCSS_TIMING_VALUE ;
\r
141 wlpw = DBI_CYCLES(timing->wlpw);
\r
142 if (wlpw > MAX_DBI_RWLPW_TIMING_VALUE) {
\r
143 wlpw = MAX_DBI_RWLPW_TIMING_VALUE ;
\r
146 #ifndef CONFIG_LCD_CS_ALWAYS_LOW
\r
147 /* dispc/lcdc will waste one cycle because CS pulse will use one cycle*/
\r
148 whpw = DBI_CYCLES (timing->whpw) - 1;
\r
150 whpw = DBI_CYCLES (timing->whpw) ;
\r
152 if (whpw > MAX_DBI_RWHPW_TIMING_VALUE) {
\r
153 whpw = MAX_DBI_RWHPW_TIMING_VALUE ;
\r
156 return (whpw | (wlpw << 6) | (wcss << 12)
\r
157 | (rhpw << 16) |(rlpw << 22) | (rcss << 28));
\r
160 static uint32_t mcu_readid(struct panel_spec *self)
\r
164 /* default id reg is 0 */
\r
165 self->info.mcu->ops->send_cmd(0x0);
\r
167 if(self->info.mcu->bus_width == 8) {
\r
168 id = (self->info.mcu->ops->read_data()) & 0xff;
\r
170 id |= (self->info.mcu->ops->read_data()) & 0xff;
\r
172 id = self->info.mcu->ops->read_data();
\r
178 #ifdef CONFIG_FB_LCD_CS1
\r
180 void mcu_dispc_init_config(struct panel_spec *panel)
\r
182 uint32_t reg_val = 0;
\r
184 FB_PRINT("sprdfb: [%s] for cs1\n", __FUNCTION__);
\r
187 printf("sprdfb: [%s] fail.(Invalid Param)\n", __FUNCTION__);
\r
191 if(SPRDFB_PANEL_TYPE_MCU != panel->type){
\r
192 printf("sprdfb: [%s] fail.(not mcu panel)\n", __FUNCTION__);
\r
196 /*use dbi as interface*/
\r
197 dispc_set_bits((2<<1), DISPC_CTRL);
\r
199 /* CS1 bus mode [BIT8]: 8080/6800 */
\r
200 switch (panel->info.mcu->bus_mode) {
\r
209 /* CS1 bus width [BIT11:9] */
\r
210 switch (panel->info.mcu->bus_width) {
\r
214 reg_val |= (1 << 9);
\r
217 reg_val |= (2 << 9);
\r
220 reg_val |= (3 << 9) ;
\r
223 reg_val |= (4 << 9);
\r
229 /*CS1 pixel bits [BIT13:12]*/
\r
230 switch (panel->info.mcu->bpp) {
\r
234 reg_val |= (1 << 12) ;
\r
237 reg_val |= (2 << 12);
\r
243 #ifndef CONFIG_FB_NO_FMARK
\r
245 reg_val |= (1 << 16);
\r
246 if(SPRDFB_POLARITY_NEG == panel->info.mcu->te_pol){
\r
247 reg_val |= (1<< 17);
\r
249 dispc_write(panel->info.mcu->te_sync_delay, DISPC_TE_SYNC_DELAY);
\r
252 #ifdef CONFIG_LCD_CS_ALWAYS_LOW
\r
253 /*CS alway low mode*/
\r
254 reg_val |= (1<<21);
\r
256 /*CS not alway low mode*/
\r
260 reg_val |= (1 << 20);
\r
262 dispc_write(reg_val, DISPC_DBI_CTRL);
\r
264 FB_PRINT("sprdfb: [%s] DISPC_DBI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DBI_CTRL));
\r
267 void mcu_dispc_set_timing(struct sprdfb_device *dev, uint32_t type)
\r
269 FB_PRINT("sprdfb: [%s] for cs1, type = %d\n", __FUNCTION__, type);
\r
273 case MCU_LCD_REGISTER_TIMING:
\r
274 dispc_write(dev->panel_timing.mcu_timing[MCU_LCD_REGISTER_TIMING],DISPC_DBI_TIMING1);
\r
277 case MCU_LCD_GRAM_TIMING:
\r
278 dispc_write(dev->panel_timing.mcu_timing[MCU_LCD_GRAM_TIMING],DISPC_DBI_TIMING1);
\r
287 void mcu_dispc_init_config(struct panel_spec *panel)
\r
289 uint32_t reg_val = 0;
\r
291 FB_PRINT("sprdfb: [%s] for cs0\n", __FUNCTION__);
\r
294 printf("sprdfb: [%s] fail.(Invalid Param)\n", __FUNCTION__);
\r
298 if(SPRDFB_PANEL_TYPE_MCU != panel->type){
\r
299 printf("sprdfb: [%s] fail.(not mcu panel)\n", __FUNCTION__);
\r
303 /*use dbi as interface*/
\r
304 dispc_set_bits((2<<1), DISPC_CTRL);
\r
306 /* CS0 bus mode [BIT0]: 8080/6800 */
\r
307 switch (panel->info.mcu->bus_mode) {
\r
316 /* CS0 bus width [BIT3:1] */
\r
317 switch (panel->info.mcu->bus_width) {
\r
321 reg_val |= (1 << 1);
\r
324 reg_val |= (2 << 1);
\r
327 reg_val |= (3 << 1) ;
\r
330 reg_val |= (4 << 1);
\r
336 /*CS0 pixel bits [BIT5:4]*/
\r
337 switch (panel->info.mcu->bpp) {
\r
341 reg_val |= (1 << 4) ;
\r
344 reg_val |= (2 << 4);
\r
350 #ifndef CONFIG_FB_NO_FMARK
\r
352 reg_val |= (1 << 16);
\r
353 if(SPRDFB_POLARITY_NEG == panel->info.mcu->te_pol){
\r
354 reg_val |= (1<< 17);
\r
356 dispc_write(panel->info.mcu->te_sync_delay, DISPC_TE_SYNC_DELAY);
\r
359 #ifdef CONFIG_LCD_CS_ALWAYS_LOW
\r
360 /*CS alway low mode*/
\r
361 reg_val |= (1<<21);
\r
363 /*CS not alway low mode*/
\r
368 dispc_write(reg_val, DISPC_DBI_CTRL);
\r
370 FB_PRINT("sprdfb: [%s] DISPC_DBI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DBI_CTRL));
\r
373 void mcu_dispc_set_timing(struct sprdfb_device *dev, uint32_t type)
\r
375 FB_PRINT("sprdfb: [%s] for cs0, type = %d\n", __FUNCTION__, type);
\r
379 case MCU_LCD_REGISTER_TIMING:
\r
380 dispc_write(dev->panel_timing.mcu_timing[MCU_LCD_REGISTER_TIMING],DISPC_DBI_TIMING0);
\r
383 case MCU_LCD_GRAM_TIMING:
\r
384 dispc_write(dev->panel_timing.mcu_timing[MCU_LCD_GRAM_TIMING],DISPC_DBI_TIMING0);
\r
392 static int32_t sprdfb_mcu_panel_check(struct panel_spec *panel)
\r
394 struct info_mcu* mcu_info = NULL;
\r
398 printf("sprdfb: [%s] fail. (Invalid param)\n", __FUNCTION__);
\r
402 if(SPRDFB_PANEL_TYPE_MCU != panel->type){
\r
403 printf("sprdfb: [%s] fail. (not mcu param)\n", __FUNCTION__);
\r
407 mcu_info = panel->info.mcu;
\r
409 FB_PRINT("sprdfb: [%s]: bus width= %d, bpp = %d\n",__FUNCTION__, mcu_info->bus_width, mcu_info->bpp);
\r
411 switch(mcu_info->bus_width){
\r
413 if((16 != mcu_info->bpp) && (24 != mcu_info->bpp)){
\r
418 if(18 != mcu_info->bpp) {
\r
423 if((16 != mcu_info->bpp) && (18 != mcu_info->bpp) &&
\r
424 (24 != mcu_info->bpp)){
\r
429 if(18 != mcu_info->bpp){
\r
434 if(24 != mcu_info->bpp){
\r
444 FB_PRINT("sprdfb: mcu_panel_check return false!\n");
\r
450 static void sprdfb_mcu_panel_mount(struct sprdfb_device *dev)
\r
452 struct timing_mcu* timing = NULL;
\r
454 if((NULL == dev) || (NULL == dev->panel)){
\r
455 printf("sprdfb: [%s]: Invalid Param\n", __FUNCTION__);
\r
459 FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
\r
461 dev->panel_if_type = SPRDFB_PANEL_IF_DBI;
\r
463 dev->panel->info.mcu->ops = &dispc_mcu_ops;
\r
465 if(NULL == dev->panel->ops->panel_readid){
\r
466 dev->panel->ops->panel_readid = mcu_readid;
\r
469 timing = dev->panel->info.mcu->timing;
\r
470 dev->panel_timing.mcu_timing[MCU_LCD_REGISTER_TIMING] = mcu_calc_timing(timing);
\r
472 dev->panel_timing.mcu_timing[MCU_LCD_GRAM_TIMING] = mcu_calc_timing(timing);
\r
475 static void sprdfb_mcu_panel_init(struct sprdfb_device *dev)
\r
477 mcu_dispc_init_config(dev->panel);
\r
478 mcu_dispc_set_timing(dev, MCU_LCD_REGISTER_TIMING);
\r
481 static void sprdfb_mcu_panel_before_refresh(struct sprdfb_device *dev)
\r
483 mcu_dispc_set_timing(dev, MCU_LCD_GRAM_TIMING);
\r
486 static void sprdfb_mcu_panel_after_refresh(struct sprdfb_device *dev)
\r
488 mcu_dispc_set_timing(dev, MCU_LCD_REGISTER_TIMING);
\r
491 struct panel_if_ctrl sprdfb_mcu_ctrl = {
\r
493 .panel_if_check = sprdfb_mcu_panel_check,
\r
494 .panel_if_mount = sprdfb_mcu_panel_mount,
\r
495 .panel_if_init = sprdfb_mcu_panel_init,
\r
496 .panel_if_before_refresh = sprdfb_mcu_panel_before_refresh,
\r
497 .panel_if_after_refresh = sprdfb_mcu_panel_after_refresh,
\r