2 * Copyright (C) 2012 Spreadtrum Communications Inc.
\r
6 #include <asm/arch/sprd_lcd.h>
\r
7 #include <asm/arch/dispc_reg.h>
\r
9 #include "sprdfb_chip_common.h"
\r
12 extern struct ops_i2c sprdfb_i2c_ops;
\r
13 extern struct ops_spi sprdfb_spi_ops;
\r
15 extern uint16_t sprdfb_i2c_init(struct sprdfb_device *dev);
\r
16 extern uint16_t sprdfb_i2c_uninit(struct sprdfb_device *dev);
\r
17 extern uint16_t sprdfb_spi_init(struct sprdfb_device *dev);
\r
18 extern uint16_t sprdfb_spi_uninit(struct sprdfb_device *dev);
\r
21 static uint32_t rgb_readid(struct panel_spec *self)
\r
24 struct info_rgb *rgb = self->info.rgb;
\r
26 /* default id reg is 0 */
\r
27 if(SPRDFB_RGB_BUS_TYPE_I2C == rgb->cmd_bus_mode){
\r
28 rgb->bus_info.i2c->ops->i2c_read_16bits(rgb->bus_info.i2c->i2c_addr , 0x0, FALSE, &id, FALSE);
\r
30 rgb->bus_info.spi->ops->spi_send_cmd(0x0);
\r
31 rgb->bus_info.spi->ops->spi_read(&id);
\r
37 static void rgb_dispc_init_config(struct panel_spec *panel)
\r
39 uint32_t reg_val = 0;
\r
41 FB_PRINT("sprdfb: [%s]\n", __FUNCTION__);
\r
44 printf("sprdfb: [%s] fail.(Invalid Param)\n", __FUNCTION__);
\r
48 if(SPRDFB_PANEL_TYPE_RGB != panel->type && SPRDFB_PANEL_TYPE_LVDS != panel->type){
\r
49 printf("sprdfb: [%s] fail.(not rgb panel)\n", __FUNCTION__);
\r
53 /*use dpi as interface*/
\r
54 dispc_clear_bits((3<<1), DISPC_CTRL);
\r
57 if(SPRDFB_POLARITY_NEG == panel->info.rgb->h_sync_pol){
\r
62 if(SPRDFB_POLARITY_NEG == panel->info.rgb->v_sync_pol){
\r
67 if(SPRDFB_POLARITY_NEG == panel->info.rgb->de_pol){
\r
72 reg_val &= ~ (1<<3);
\r
75 switch(panel->info.rgb->video_bus_width){
\r
79 reg_val |= (1 << 6);
\r
82 reg_val |= (2 << 6);
\r
88 dispc_write(reg_val, DISPC_DPI_CTRL);
\r
90 FB_PRINT("sprdfb: [%s] DISPC_DPI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DPI_CTRL));
\r
93 static void rgb_dispc_set_timing(struct sprdfb_device *dev)
\r
95 FB_PRINT("sprdfb: [%s]\n", __FUNCTION__);
\r
97 dispc_write(dev->panel_timing.rgb_timing[RGB_LCD_H_TIMING], DISPC_DPI_H_TIMING);
\r
98 dispc_write(dev->panel_timing.rgb_timing[RGB_LCD_V_TIMING], DISPC_DPI_V_TIMING);
\r
101 uint32_t rgb_calc_h_timing(struct timing_rgb *timing)
\r
105 uint32_t hsync, hbp, hfp;
\r
106 // struct clk * clk = NULL;
\r
108 if(NULL == timing){
\r
109 FB_PRINT("sprdfb: [%s]: Invalid Param\n", __FUNCTION__);
\r
113 // clk_get(NULL,"clk_dispc_dpi");
\r
114 // clk_rate = clk_get_rate(clk) / 1000000;
\r
115 clk_rate = 250; // 250 MHz
\r
117 FB_PRINT("sprdfb: [%s] clk_rate: 0x%x\n", __FUNCTION__, clk_rate);
\r
119 /********************************************************
\r
120 * we assume : t = ? ns, dispc_dpi = ? MHz so
\r
121 * 1ns need cycle : dispc_dpi /1000
\r
122 * tns need cycles : t * dispc_dpi / 1000
\r
124 ********************************************************/
\r
125 #define MAX_DPI_HSYNC_TIMING_VALUE 255
\r
126 #define MAX_DPI_HBP_TIMING_VALUE 4095
\r
127 #define MAX_DPI_HFP_TIMING_VALUE 4095
\r
128 #define DPI_CYCLES(ns) (( (ns) * clk_rate + 1000 - 1)/ 1000)
\r
131 hsync = DPI_CYCLES(timing->hsync);
\r
132 if (hsync > MAX_DPI_HSYNC_TIMING_VALUE) {
\r
133 hsync = MAX_DPI_HSYNC_TIMING_VALUE ;
\r
136 hbp = DPI_CYCLES(timing->hbp);
\r
137 if (hbp > MAX_DPI_HSYNC_TIMING_VALUE) {
\r
138 hbp = MAX_DPI_HSYNC_TIMING_VALUE ;
\r
141 hfp = DPI_CYCLES (timing->hfp);
\r
142 if (hfp > MAX_DPI_HFP_TIMING_VALUE) {
\r
143 hfp = MAX_DPI_HFP_TIMING_VALUE ;
\r
146 return (hsync | (hbp << 8) | (hfp << 20));
\r
148 return (timing->hsync | (timing->hbp << 8) | (timing->hfp << 20));
\r
153 uint32_t rgb_calc_v_timing(struct timing_rgb *timing)
\r
155 return (timing->vsync| (timing->vbp << 8) | (timing->vfp << 20));
\r
158 static int32_t sprdfb_rgb_panel_check(struct panel_spec *panel)
\r
161 printf("sprdfb: [%s] fail. (Invalid param)\n", __FUNCTION__);
\r
165 if(SPRDFB_PANEL_TYPE_RGB != panel->type && SPRDFB_PANEL_TYPE_LVDS != panel->type){
\r
166 printf("sprdfb: [%s] fail. (not rgb param)\n", __FUNCTION__);
\r
170 FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
\r
175 static void sprdfb_rgb_panel_mount(struct sprdfb_device *dev)
\r
177 if((NULL == dev) || (NULL == dev->panel)){
\r
178 printf("sprdfb: [%s]: Invalid Param\n", __FUNCTION__);
\r
182 FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
\r
184 dev->panel_if_type = SPRDFB_PANEL_IF_DPI;
\r
186 if(SPRDFB_RGB_BUS_TYPE_I2C == dev->panel->info.rgb->cmd_bus_mode){
\r
187 dev->panel->info.rgb->bus_info.i2c->ops = &sprdfb_i2c_ops;
\r
189 dev->panel->info.rgb->bus_info.spi->ops = &sprdfb_spi_ops;
\r
192 if(NULL == dev->panel->ops->panel_readid){
\r
193 dev->panel->ops->panel_readid = rgb_readid;
\r
196 dev->panel_timing.rgb_timing[RGB_LCD_H_TIMING] = rgb_calc_h_timing(dev->panel->info.rgb->timing);
\r
197 dev->panel_timing.rgb_timing[RGB_LCD_V_TIMING] = rgb_calc_v_timing(dev->panel->info.rgb->timing);
\r
200 static void sprdfb_rgb_panel_init(struct sprdfb_device *dev)
\r
202 if(SPRDFB_RGB_BUS_TYPE_I2C == dev->panel->info.rgb->cmd_bus_mode){
\r
203 sprdfb_i2c_init(dev);
\r
204 }else if(SPRDFB_RGB_BUS_TYPE_SPI == dev->panel->info.rgb->cmd_bus_mode) {
\r
205 sprdfb_spi_init(dev);
\r
207 rgb_dispc_init_config(dev->panel);
\r
208 rgb_dispc_set_timing(dev);
\r
210 dispc_set_bits((1 << 4), DISPC_CTRL); //rgb panel need to out put clock before init
\r
212 dispc_clear_bits((1 << 4), DISPC_CTRL);
\r
214 #ifdef SPRDFB_SUPPORT_LVDS_PANEL
\r
215 if (dev->panel->type == SPRDFB_PANEL_TYPE_LVDS) {
\r
216 /* The following register is used for the actual SharkL Chip tape-out */
\r
217 printf("sprdfb: [%s]: Now initialize host LVDS mode\n", __FUNCTION__);
\r
218 /* bit[16] clk from LVDS TX (need set when in LVDS mode) */
\r
219 __raw_writel((1 << 16), REG_AP_CLK_DISPC0_DPI_CFG);
\r
220 /* 0xa4, bit[0]: LVDS AP select */
\r
221 /* 0x3060, bit[0]: LVDS TX power down (active '1') */
\r
222 __raw_writel((1 << 0), REG_PMU_APB_LVDSDIS_PLL_REL_CFG);
\r
223 __raw_writel((1 << 0), REG_AON_APB_LVDS_CFG);
\r
225 /* '0': R/G/B[1:0] sent by lan3; '1': RGB[7:6] sent by lan3 */
\r
226 dispc_set_bits((1 << 21), DISPC_LVDS_CTRL);
\r
231 static void sprdfb_rgb_panel_uninit(struct sprdfb_device *dev)
\r
233 if(SPRDFB_RGB_BUS_TYPE_I2C == dev->panel->info.rgb->cmd_bus_mode){
\r
234 sprdfb_i2c_uninit(dev);
\r
235 }else if(SPRDFB_RGB_BUS_TYPE_SPI == dev->panel->info.rgb->cmd_bus_mode) {
\r
236 sprdfb_spi_uninit(dev);
\r
240 struct panel_if_ctrl sprdfb_rgb_ctrl = {
\r
242 .panel_if_check = sprdfb_rgb_panel_check,
\r
243 .panel_if_mount = sprdfb_rgb_panel_mount,
\r
244 .panel_if_init = sprdfb_rgb_panel_init,
\r
245 .panel_if_uninit = sprdfb_rgb_panel_uninit,
\r
246 .panel_if_before_refresh = NULL,
\r
247 .panel_if_after_refresh = NULL,
\r