1 #include <linux/module.h>
2 #include <linux/init.h>
4 #include <linux/device.h>
5 #include <linux/delay.h>
7 #include <linux/mfd/rk610_core.h>
9 #include <mach/iomux.h>
10 #include <linux/err.h>
11 #include <linux/slab.h>
13 #if defined(CONFIG_ARCH_RK3066B)
14 #define RK610_RESET_PIN RK30_PIN2_PC5
15 #elif defined(CONFIG_ARCH_RK30)
16 #define RK610_RESET_PIN RK30_PIN0_PC6
18 #define RK610_RESET_PIN RK29_PIN6_PC1
25 #define DBG(x...) printk(KERN_INFO x)
30 static struct i2c_client *rk610_control_client = NULL;
31 #ifdef CONFIG_RK610_LVDS
32 extern int rk610_lcd_init(struct rk610_core_info *rk610_core_info);
34 int rk610_lcd_init(struct rk610_core_info *rk610_core_info){}
36 int rk610_control_send_byte(const char reg, const char data)
40 DBG("reg = 0x%02x, val=0x%02x\n", reg ,data);
42 if(rk610_control_client == NULL)
44 //i2c_master_reg8_send
45 ret = i2c_master_reg8_send(rk610_control_client, reg, &data, 1, 100*1000);
52 #ifdef CONFIG_SND_SOC_RK610
53 static unsigned int current_pll_value = 0;
54 int rk610_codec_pll_set(unsigned int rate)
60 if(current_pll_value == rate)
63 // Input clock is 12MHz.
64 if(rate == 11289600) {
65 // For 11.2896MHz, N = 2 M= 75 F = 0.264(0x43958) NO = 8
72 else if(rate == 12288000) {
73 // For 12.2888MHz, N = 2 M= 75 F = 0.92(0xEB851) NO = 8
81 printk(KERN_ERR "[%s] not support such frequency\n", __FUNCTION__);
85 //Enable codec pll fractional number and power down.
87 rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON5, data);
91 rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON0, data);
94 rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON1, data);
97 rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON2, data);
98 data = (F >> 8) & 0xFF;
99 rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON3, data);
100 data = (F >> 16) & 0xFF;
101 rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON4, data);
103 // i2s mclk = codec_pll/5;
104 i2c_master_reg8_recv(rk610_control_client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000);
105 data &= ~CLOCK_CON1_I2S_DVIDER_MASK;
107 rk610_control_send_byte(RK610_CONTROL_REG_CLOCK_CON1, data);
109 // Power up codec pll.
110 data |= C_PLL_POWER_ON;
111 rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON5, data);
113 current_pll_value = rate;
114 DBG("[%s] rate %u\n", __FUNCTION__, rate);
119 void rk610_control_init_codec(void)
121 struct i2c_client *client = rk610_control_client;
125 if(rk610_control_client == NULL)
127 DBG("[%s] start\n", __FUNCTION__);
129 //gpio_set_value(RK610_RESET_PIN, GPIO_LOW); //reset rk601
131 //gpio_set_value(RK610_RESET_PIN, GPIO_HIGH);
134 // Set i2c glitch timeout.
136 ret = i2c_master_reg8_send(client, RK610_CONTROL_REG_I2C_CON, &data, 1, 20*1000);
138 // rk610_codec_pll_set(11289600);
140 //use internal codec, enable DAC ADC LRCK output.
141 // i2c_master_reg8_recv(client, RK610_CONTROL_REG_CODEC_CON, &data, 1, 100*1000);
142 // data = CODEC_CON_BIT_DAC_LRCL_OUTPUT_DISABLE | CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE;
143 // data = CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE;
145 rk610_control_send_byte(RK610_CONTROL_REG_CODEC_CON, data);
147 // Select internal i2s clock from codec_pll.
148 i2c_master_reg8_recv(rk610_control_client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000);
149 // data |= CLOCK_CON1_I2S_CLK_CODEC_PLL;
151 rk610_control_send_byte(RK610_CONTROL_REG_CLOCK_CON1, data);
153 i2c_master_reg8_recv(client, RK610_CONTROL_REG_CODEC_CON, &data, 1, 100*1000);
154 DBG("[%s] RK610_CONTROL_REG_CODEC_CON is %x\n", __FUNCTION__, data);
156 i2c_master_reg8_recv(client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000);
157 DBG("[%s] RK610_CONTROL_REG_CLOCK_CON1 is %x\n", __FUNCTION__, data);
162 static int rk610_read_p0_reg(struct i2c_client *client, char reg, char *val)
164 return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
167 static int rk610_write_p0_reg(struct i2c_client *client, char reg, char *val)
169 return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
171 static ssize_t rk610_show_reg_attrs(struct device *dev,
172 struct device_attribute *attr,
178 struct i2c_client *client=rk610_control_client;
182 rk610_read_p0_reg(client, i, &val);
184 size += sprintf(buf+size,"\n>>>rk610_ctl %x:",i);
185 size += sprintf(buf+size," %2x",val);
190 static ssize_t rk610_store_reg_attrs(struct device *dev,
191 struct device_attribute *attr,
192 const char *buf, size_t size)
194 struct i2c_client *client=NULL;
195 static char val=0,reg=0;
196 client = rk610_control_client;
197 DBG("/**********rk610 reg config******/");
199 sscanf(buf, "%x%x", &val,®);
200 DBG("reg=%x val=%x\n",reg,val);
201 rk610_write_p0_reg(client, reg, &val);
206 #define LCD_CS_PIN RK30_PIN2_PB6
207 #define LCD_CS_VALUE GPIO_HIGH
209 #define LCD_EN_PIN RK30_PIN0_PB0
210 #define LCD_EN_VALUE GPIO_LOW
212 #define LCD_STB_PIN RK30_PIN2_PB3
213 #define LCD_STB_VALUE GPIO_HIGH
215 static ssize_t rk610_show_gpio_attrs(struct device *dev,
216 struct device_attribute *attr,
221 printk("gpio2b6 lcd_cs =%d\n",gpio_get_value(LCD_CS_PIN));
222 printk("gpio0b0 lcd_en =%d\n",gpio_get_value(LCD_EN_PIN));
223 printk("gpio2b3 lcd_stb =%d\n",gpio_get_value(LCD_STB_PIN));
226 static ssize_t rk610_store_gpio_attrs(struct device *dev,
227 struct device_attribute *attr,
228 const char *buf, size_t size)
230 struct i2c_client *client=NULL;
231 static char val=0,reg=0;
232 sscanf(buf, "%x%x", &val,®);
234 DBG("reg=%x val=%x\n",reg,val);
237 gpio_set_value(LCD_CS_PIN,val&1);
240 gpio_set_value(LCD_EN_PIN,val&1);
243 gpio_set_value(LCD_STB_PIN,val&1);
246 printk("gpio2b6 lcd_cs =%d\n",gpio_get_value(LCD_CS_PIN));
247 printk("gpio0b0 lcd_en =%d\n",gpio_get_value(LCD_EN_PIN));
248 printk("gpio2b3 lcd_stb =%d\n",gpio_get_value(LCD_STB_PIN));
251 static struct device_attribute rk610_attrs[] = {
252 __ATTR(reg_ctl, 0777,rk610_show_reg_attrs,rk610_store_reg_attrs),
253 __ATTR(gpio_ctl, 0777,rk610_show_gpio_attrs,rk610_store_gpio_attrs),
257 static int rk610_control_probe(struct i2c_client *client,
258 const struct i2c_device_id *id)
262 struct rk610_core_info *core_info = NULL;
263 struct rk610_ctl_platform_data *pdata = client->dev.platform_data;
264 DBG("[%s] start\n", __FUNCTION__);
265 core_info = kmalloc(sizeof(struct rk610_core_info), GFP_KERNEL);
268 dev_err(&client->dev, ">> rk610 core inf kmalloc fail!");
271 memset(core_info, 0, sizeof(struct rk610_core_info));
272 core_info->pdata = pdata;
273 #if defined(CONFIG_SND_RK29_SOC_I2S_8CH)
274 iis_clk = clk_get_sys("rk29_i2s.0", "i2s");
275 #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH)
276 iis_clk = clk_get_sys("rk29_i2s.1", "i2s");
278 iis_clk = clk_get_sys("rk29_i2s.2", "i2s");
280 if (IS_ERR(iis_clk)) {
281 printk("failed to get i2s clk\n");
282 ret = PTR_ERR(iis_clk);
284 DBG("got i2s clk ok!\n");
286 clk_set_rate(iis_clk, 11289600);
287 #if defined(CONFIG_ARCH_RK29)
288 rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK);
289 #elif defined(CONFIG_ARCH_RK3066B)
290 rk30_mux_api_set(GPIO1C0_I2SCLK_NAME, GPIO1C_I2SCLK);
291 #elif defined(CONFIG_ARCH_RK30)
292 rk30_mux_api_set(GPIO0B0_I2S8CHCLK_NAME, GPIO0B_I2S_8CH_CLK);
297 rk610_control_client = client;
299 if(core_info->pdata->rk610_power_on_init)
300 core_info->pdata->rk610_power_on_init();
301 core_info->client = client;
302 rk610_lcd_init(core_info);
304 device_create_file(&(client->dev), &rk610_attrs[0]);
305 device_create_file(&(client->dev), &rk610_attrs[1]);
310 static int rk610_control_remove(struct i2c_client *client)
315 static const struct i2c_device_id rk610_control_id[] = {
319 MODULE_DEVICE_TABLE(i2c, rk610_control_id);
321 static struct i2c_driver rk610_control_driver = {
325 .probe = rk610_control_probe,
326 .remove = rk610_control_remove,
327 .id_table = rk610_control_id,
330 static int __init rk610_control_init(void)
332 DBG("[%s] start\n", __FUNCTION__);
333 return i2c_add_driver(&rk610_control_driver);
336 static void __exit rk610_control_exit(void)
338 i2c_del_driver(&rk610_control_driver);
341 subsys_initcall_sync(rk610_control_init);
342 //module_init(rk610_control_init);
343 module_exit(rk610_control_exit);
346 MODULE_DESCRIPTION("RK610 control driver");
347 MODULE_AUTHOR("Rock-chips, <www.rock-chips.com>");
348 MODULE_LICENSE("GPL");