2 * Copyright (C) 2012 Spreadtrum Communications Inc.
\r
4 * This software is licensed under the terms of the GNU General Public
\r
5 * License version 2, as published by the Free Software Foundation, and
\r
6 * may be copied, distributed, and modified under those terms.
\r
8 * This program is distributed in the hope that it will be useful,
\r
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
11 * GNU General Public License for more details.
\r
15 #include <asm/arch/tiger_lcd.h>
\r
16 #include <asm/arch/dispc_reg.h>
\r
20 extern struct ops_i2c sprdfb_i2c_ops;
\r
21 extern struct ops_spi sprdfb_spi_ops;
\r
23 extern uint16_t sprdfb_i2c_init(struct sprdfb_device *dev);
\r
24 extern uint16_t sprdfb_i2c_uninit(struct sprdfb_device *dev);
\r
25 extern uint16_t sprdfb_spi_init(struct sprdfb_device *dev);
\r
26 extern uint16_t sprdfb_spi_uninit(struct sprdfb_device *dev);
\r
29 static uint32_t rgb_readid(struct panel_spec *self)
\r
32 struct info_rgb *rgb = self->info.rgb;
\r
34 /* default id reg is 0 */
\r
35 if(SPRDFB_RGB_BUS_TYPE_I2C == rgb->cmd_bus_mode){
\r
36 rgb->bus_info.i2c->ops->i2c_read_16bits(rgb->bus_info.i2c->i2c_addr , 0x0, FALSE, &id, FALSE);
\r
38 rgb->bus_info.spi->ops->spi_send_cmd(0x0);
\r
39 rgb->bus_info.spi->ops->spi_read(&id);
\r
45 static void rgb_dispc_init_config(struct panel_spec *panel)
\r
47 uint32_t reg_val = 0;
\r
49 FB_PRINT("sprdfb: [%s]\n", __FUNCTION__);
\r
52 FB_PRINT("sprdfb: [%s] fail.(Invalid Param)\n", __FUNCTION__);
\r
56 if(SPRDFB_PANEL_TYPE_RGB != panel->type){
\r
57 FB_PRINT("sprdfb: [%s] fail.(not rgb panel)\n", __FUNCTION__);
\r
61 /*use dpi as interface*/
\r
62 dispc_clear_bits((3<<1), DISPC_CTRL);
\r
65 if(SPRDFB_POLARITY_NEG == panel->info.rgb->h_sync_pol){
\r
70 if(SPRDFB_POLARITY_NEG == panel->info.rgb->v_sync_pol){
\r
75 if(SPRDFB_POLARITY_NEG == panel->info.rgb->de_pol){
\r
80 reg_val &= ~ (1<<3);
\r
83 switch(panel->info.rgb->video_bus_width){
\r
87 reg_val |= (1 << 6);
\r
90 reg_val |= (2 << 6);
\r
96 dispc_write(reg_val, DISPC_DPI_CTRL);
\r
98 FB_PRINT("sprdfb: [%s] DISPC_DPI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DPI_CTRL));
\r
101 static void rgb_dispc_set_timing(struct sprdfb_device *dev)
\r
103 FB_PRINT("sprdfb: [%s]\n", __FUNCTION__);
\r
105 dispc_write(dev->panel_timing.rgb_timing[RGB_LCD_H_TIMING], DISPC_DPI_H_TIMING);
\r
106 dispc_write(dev->panel_timing.rgb_timing[RGB_LCD_V_TIMING], DISPC_DPI_V_TIMING);
\r
109 uint32_t rgb_calc_h_timing(struct timing_rgb *timing)
\r
113 uint32_t hsync, hbp, hfp;
\r
114 // struct clk * clk = NULL;
\r
116 if(NULL == timing){
\r
117 FB_PRINT("sprdfb: [%s]: Invalid Param\n", __FUNCTION__);
\r
121 // clk_get(NULL,"clk_dispc_dpi");
\r
122 // clk_rate = clk_get_rate(clk) / 1000000;
\r
123 clk_rate = 250; // 250 MHz
\r
125 FB_PRINT("sprdfb: [%s] clk_rate: 0x%x\n", __FUNCTION__, clk_rate);
\r
127 /********************************************************
\r
128 * we assume : t = ? ns, dispc_dpi = ? MHz so
\r
129 * 1ns need cycle : dispc_dpi /1000
\r
130 * tns need cycles : t * dispc_dpi / 1000
\r
132 ********************************************************/
\r
133 #define MAX_DPI_HSYNC_TIMING_VALUE 255
\r
134 #define MAX_DPI_HBP_TIMING_VALUE 4095
\r
135 #define MAX_DPI_HFP_TIMING_VALUE 4095
\r
136 #define DPI_CYCLES(ns) (( (ns) * clk_rate + 1000 - 1)/ 1000)
\r
139 hsync = DPI_CYCLES(timing->hsync);
\r
140 if (hsync > MAX_DPI_HSYNC_TIMING_VALUE) {
\r
141 hsync = MAX_DPI_HSYNC_TIMING_VALUE ;
\r
144 hbp = DPI_CYCLES(timing->hbp);
\r
145 if (hbp > MAX_DPI_HSYNC_TIMING_VALUE) {
\r
146 hbp = MAX_DPI_HSYNC_TIMING_VALUE ;
\r
149 hfp = DPI_CYCLES (timing->hfp);
\r
150 if (hfp > MAX_DPI_HFP_TIMING_VALUE) {
\r
151 hfp = MAX_DPI_HFP_TIMING_VALUE ;
\r
154 return (hsync | (hbp << 8) | (hfp << 20));
\r
156 return (timing->hsync | (timing->hbp << 8) | (timing->hfp << 20));
\r
161 uint32_t rgb_calc_v_timing(struct timing_rgb *timing)
\r
163 return (timing->vsync| (timing->vbp << 8) | (timing->vfp << 20));
\r
166 static int32_t sprdfb_rgb_panel_check(struct panel_spec *panel)
\r
169 FB_PRINT("sprdfb: [%s] fail. (Invalid param)\n", __FUNCTION__);
\r
173 if(SPRDFB_PANEL_TYPE_RGB != panel->type){
\r
174 FB_PRINT("sprdfb: [%s] fail. (not rgb param)\n", __FUNCTION__);
\r
178 FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
\r
183 static void sprdfb_rgb_panel_mount(struct sprdfb_device *dev)
\r
185 if((NULL == dev) || (NULL == dev->panel)){
\r
186 FB_PRINT("sprdfb: [%s]: Invalid Param\n", __FUNCTION__);
\r
190 FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
\r
192 dev->panel_if_type = SPRDFB_PANEL_IF_DPI;
\r
194 if(SPRDFB_RGB_BUS_TYPE_I2C == dev->panel->info.rgb->cmd_bus_mode){
\r
195 dev->panel->info.rgb->bus_info.i2c->ops = &sprdfb_i2c_ops;
\r
197 dev->panel->info.rgb->bus_info.spi->ops = &sprdfb_spi_ops;
\r
200 if(NULL == dev->panel->ops->panel_readid){
\r
201 dev->panel->ops->panel_readid = rgb_readid;
\r
204 dev->panel_timing.rgb_timing[RGB_LCD_H_TIMING] = rgb_calc_h_timing(dev->panel->info.rgb->timing);
\r
205 dev->panel_timing.rgb_timing[RGB_LCD_V_TIMING] = rgb_calc_v_timing(dev->panel->info.rgb->timing);
\r
208 static void sprdfb_rgb_panel_init(struct sprdfb_device *dev)
\r
210 if(SPRDFB_RGB_BUS_TYPE_I2C == dev->panel->info.rgb->cmd_bus_mode){
\r
211 sprdfb_i2c_init(dev);
\r
212 }else if(SPRDFB_RGB_BUS_TYPE_SPI == dev->panel->info.rgb->cmd_bus_mode) {
\r
213 sprdfb_spi_init(dev);
\r
216 rgb_dispc_init_config(dev->panel);
\r
217 rgb_dispc_set_timing(dev);
\r
219 dispc_set_bits((1 << 4), DISPC_CTRL); //rgb panel need to out put clock before init
\r
221 dispc_clear_bits((1 << 4), DISPC_CTRL);
\r
224 static void sprdfb_rgb_panel_uninit(struct sprdfb_device *dev)
\r
226 if(SPRDFB_RGB_BUS_TYPE_I2C == dev->panel->info.rgb->cmd_bus_mode){
\r
227 sprdfb_i2c_uninit(dev);
\r
228 }else if(SPRDFB_RGB_BUS_TYPE_SPI == dev->panel->info.rgb->cmd_bus_mode) {
\r
229 sprdfb_spi_uninit(dev);
\r
233 struct panel_if_ctrl sprdfb_rgb_ctrl = {
\r
235 .panel_if_check = sprdfb_rgb_panel_check,
\r
236 .panel_if_mount = sprdfb_rgb_panel_mount,
\r
237 .panel_if_init = sprdfb_rgb_panel_init,
\r
238 .panel_if_uninit = sprdfb_rgb_panel_uninit,
\r
239 .panel_if_before_refresh = NULL,
\r
240 .panel_if_after_refresh = NULL,
\r