mfd:rk616:vif:support hdmi only mode
[firefly-linux-kernel-4.4.55.git] / drivers / mfd / rk616-core.c
1
2 #include <linux/kernel.h>
3 #include <linux/module.h>
4 #include <linux/delay.h>
5 #include <linux/mfd/core.h>
6 #include <linux/slab.h>
7 #include <linux/mfd/rk616.h>
8 #include <mach/iomux.h>
9 #include <linux/err.h>
10 #include <linux/uaccess.h>
11 #if defined(CONFIG_DEBUG_FS)
12 #include <linux/fs.h>
13 #include <linux/debugfs.h>
14 #include <linux/seq_file.h>
15 #endif
16
17 #ifndef MHZ
18 #define MHZ (1000*1000)
19 #endif
20
21 static struct mfd_cell rk616_devs[] = {
22         {
23                 .name = "rk616-lvds",
24                 .id = 0,
25         },
26         {
27                 .name = "rk616-codec",
28                 .id = 1,
29         },
30         {
31                 .name = "rk616-hdmi",
32                 .id = 2,
33         },
34         {
35                 .name = "rk616-mipi",
36                 .id = 3,
37         },
38 };
39
40 static int rk616_i2c_read_reg(struct mfd_rk616 *rk616, u16 reg,u32 *pval)
41 {
42         struct i2c_client * client = rk616->client;
43         struct i2c_adapter *adap = client->adapter;
44         struct i2c_msg msgs[2];
45         int ret;
46         char reg_buf[2];
47         
48         memcpy(reg_buf, &reg, 2);
49
50         msgs[0].addr = client->addr;
51         msgs[0].flags = client->flags;
52         msgs[0].len = 2;
53         msgs[0].buf = reg_buf;
54         msgs[0].scl_rate = rk616->pdata->scl_rate;
55         msgs[0].udelay = client->udelay;
56
57         msgs[1].addr = client->addr;
58         msgs[1].flags = client->flags | I2C_M_RD;
59         msgs[1].len = 4;
60         msgs[1].buf = (char *)pval;
61         msgs[1].scl_rate = rk616->pdata->scl_rate;
62         msgs[1].udelay = client->udelay;
63
64         ret = i2c_transfer(adap, msgs, 2);
65
66         
67         return (ret == 2)? 4 : ret;
68
69 }
70
71 static int rk616_i2c_write_reg(struct mfd_rk616 *rk616, u16 reg,u32 *pval)
72 {
73         struct i2c_client *client = rk616->client;
74         struct i2c_adapter *adap = client->adapter;
75         struct i2c_msg msg;
76         int ret;
77         char *tx_buf = (char *)kmalloc(6, GFP_KERNEL);
78         if(!tx_buf)
79                 return -ENOMEM;
80         
81         memcpy(tx_buf, &reg, 2); 
82         memcpy(tx_buf+2, (char *)pval, 4); 
83
84         msg.addr = client->addr;
85         msg.flags = client->flags;
86         msg.len = 6;
87         msg.buf = (char *)tx_buf;
88         msg.scl_rate = rk616->pdata->scl_rate;
89         msg.udelay = client->udelay;
90
91         ret = i2c_transfer(adap, &msg, 1);
92         kfree(tx_buf);
93         
94         
95         return (ret == 1) ? 4 : ret;
96 }
97
98
99 #if defined(CONFIG_DEBUG_FS)
100 static int rk616_reg_show(struct seq_file *s, void *v)
101 {
102         int i = 0;
103         u32 val = 0;
104         struct mfd_rk616 *rk616 = s->private;
105         if(!rk616)
106         {
107                 dev_err(rk616->dev,"no mfd rk616!\n");
108                 return 0;
109         }
110
111         for(i=0;i<= CRU_CFGMISC_CON;i+=4)
112         {
113                 rk616->read_dev(rk616,i,&val);
114                 if(i%16==0)
115                         seq_printf(s,"\n0x%04x:",i);
116                 seq_printf(s," %08x",val);
117         }
118         seq_printf(s,"\n");
119
120         return 0;
121 }
122
123 static ssize_t rk616_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
124
125         struct mfd_rk616 *rk616 = file->f_path.dentry->d_inode->i_private;
126         u32 reg;
127         u32 val;
128         
129         char kbuf[25];
130         if (copy_from_user(kbuf, buf, count))
131                 return -EFAULT;
132         sscanf(kbuf, "%x%x", &reg,&val);
133         dev_dbg(rk616->dev,"%s:reg:0x%04x val:0x%08x\n",__func__,reg,val);
134         rk616->write_dev(rk616,reg,&val);
135         return count;
136 }
137
138 static int rk616_reg_open(struct inode *inode, struct file *file)
139 {
140         struct mfd_rk616 *rk616 = inode->i_private;
141         return single_open(file,rk616_reg_show,rk616);
142 }
143
144 static const struct file_operations rk616_reg_fops = {
145         .owner          = THIS_MODULE,
146         .open           = rk616_reg_open,
147         .read           = seq_read,
148         .write          = rk616_reg_write,
149         .llseek         = seq_lseek,
150         .release        = single_release,
151 };
152 #endif
153
154
155 static u32 rk616_clk_gcd(u32 numerator, u32 denominator)
156 {
157         u32 a, b;
158
159         if (!numerator || !denominator)
160                 return 0;
161
162         if (numerator > denominator) {
163                 a = numerator;
164                 b = denominator;
165         } else {
166                 a = denominator;
167                 b = numerator;
168         }
169
170         while (b != 0) {
171                 int r = b;
172                 b = a % b;
173                 a = r;
174         }
175
176         return a;
177 }
178
179
180 static int rk616_pll_par_calc(u32 fin_hz,u32 fout_hz,u32 *refdiv, u32 *fbdiv,
181                                         u32 *postdiv1, u32 *postdiv2, u32 *frac)
182 {
183         // FIXME set postdiv1/2 always 1        
184         u32 gcd;
185         u64 fin_64, frac_64;
186         u32 f_frac;
187         if(!fin_hz || !fout_hz)
188                 return -EINVAL;
189
190         if(fin_hz / MHZ * MHZ == fin_hz && fout_hz /MHZ * MHZ == fout_hz)
191         {
192                 fin_hz /= MHZ;
193                 fout_hz /= MHZ;
194                 gcd = rk616_clk_gcd(fin_hz, fout_hz);
195                 *refdiv = fin_hz / gcd;
196                 *fbdiv = fout_hz / gcd;
197                 *postdiv1 = 1;
198                 *postdiv2 = 1;
199
200                 *frac = 0;
201                 
202         } 
203         else 
204         {
205                 
206                 gcd = rk616_clk_gcd(fin_hz / MHZ, fout_hz / MHZ);
207                 *refdiv = fin_hz / MHZ / gcd;
208                 *fbdiv = fout_hz / MHZ / gcd;
209                 *postdiv1 = 1;
210                 *postdiv2 = 1;
211
212                 *frac = 0;
213
214                 f_frac = (fout_hz % MHZ);
215                 fin_64 = fin_hz;
216                 do_div(fin_64, (u64)*refdiv);
217                 frac_64 = (u64)f_frac << 24;
218                 do_div(frac_64, fin_64);
219                 *frac = (u32) frac_64;
220                 printk(KERN_INFO "frac_64=%llx, frac=%u\n", frac_64, *frac);
221         }
222         printk(KERN_INFO "fin=%u,fout=%u,gcd=%u,refdiv=%u,fbdiv=%u,postdiv1=%u,postdiv2=%u,frac=%u\n",
223                                 fin_hz, fout_hz, gcd, *refdiv, *fbdiv, *postdiv1, *postdiv2, *frac);
224         return 0;
225 }
226
227
228 static  int  rk616_pll_wait_lock(struct mfd_rk616 *rk616,int id)
229 {
230         u32 delay = 10;
231         u32 val = 0;
232         int ret;
233         int offset;
234
235         if(id == 0)  //PLL0
236         {
237                 offset = 0;
238         }
239         else // PLL1
240         {
241                 offset = 0x0c;
242         }
243         while (delay >= 1) 
244         {
245                 ret = rk616->read_dev(rk616,CRU_PLL0_CON1 + offset,&val);
246                 if (val&PLL0_LOCK)
247                 {
248                         dev_info(rk616->dev,"PLL%d locked\n",id);
249                         break;
250                 }
251                 msleep(1);
252                 delay--;
253         }
254         if (delay == 0)
255         {
256                 printk(KERN_ALERT "rk616 wait PLL%d lock time out!\n",id);
257         }
258
259         return 0;
260 }
261
262
263 int rk616_pll_set_rate(struct mfd_rk616 *rk616,int id,u32 cfg_val,u32 frac)
264 {
265         u32 val = 0;
266         int ret;
267         int offset;
268         u16 con0 = cfg_val & 0xffff;
269         u16 con1 = (cfg_val >> 16)&0xffff;
270         u32 fbdiv = con0 & 0xfff;
271         u32 postdiv1 = (con0 >> 12)&0x7;
272         u32 refdiv = con1 & 0x3f;
273         u32 postdiv2 = (con1 >> 6) & 0x7;
274         u8 mode = !frac;
275         
276         
277         if(id == 0)  //PLL0
278         {
279                 offset = 0;
280         }
281         else // PLL1
282         {
283                 offset = 0x0c;
284         }
285
286
287         val = PLL0_PWR_DN | (PLL0_PWR_DN << 16);
288         ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
289
290         val = PLL0_POSTDIV1(postdiv1) | PLL0_FBDIV(fbdiv) | PLL0_POSTDIV1_MASK | 
291                 PLL0_FBDIV_MASK | (PLL0_BYPASS << 16);
292         ret = rk616->write_dev(rk616,CRU_PLL0_CON0 + offset,&val);
293
294         val = PLL0_DIV_MODE(mode) | PLL0_POSTDIV2(postdiv2) | PLL0_REFDIV(refdiv) |
295                 (PLL0_DIV_MODE_MASK) | PLL0_POSTDIV2_MASK | PLL0_REFDIV_MASK;
296         ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
297
298         val = PLL0_FRAC(frac);
299         ret = rk616->write_dev(rk616,CRU_PLL0_CON2 + offset,&val);
300         
301         val = (PLL0_PWR_DN << 16);
302         ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
303         rk616_pll_wait_lock(rk616,id);
304
305         return 0;       
306         
307 }
308 /***********************************
309 default clk patch settiing:
310 CLKIN-------->CODEC
311 LCD_DCLK0--->PLL0--->Dither--->LVDS/MIPI
312 LCD_DCLK1--->PLL1--->HDMI
313 ************************************/
314
315 static int rk616_clk_common_init(struct mfd_rk616 *rk616)
316 {
317         u32 val = 0;
318         int ret;
319
320         val = PLL1_CLK_SEL(LCD1_DCLK) | PLL0_CLK_SEL(LCD0_DCLK) | LCD1_CLK_DIV(0) | 
321                 LCD0_CLK_DIV(0) | PLL1_CLK_SEL_MASK | PLL0_CLK_SEL_MASK | 
322                 LCD1_CLK_DIV_MASK | LCD0_CLK_DIV_MASK; //pll1 clk from lcdc1_dclk,pll0 clk from lcdc0_dclk,mux_lcdx = lcdx_clk
323         ret = rk616->write_dev(rk616,CRU_CLKSEL0_CON,&val);
324
325         val = SCLK_SEL(SCLK_SEL_PLL1) | CODEC_MCLK_SEL(CODEC_MCLK_SEL_12M) |
326                 CODEC_MCLK_SEL_MASK | SCLK_SEL_MASK; //codec mclk from clkin
327         ret = rk616->write_dev(rk616,CRU_CLKSEL1_CON,&val);
328         
329         val = 0; //codec mck = clkin
330         ret = rk616->write_dev(rk616,CRU_CODEC_DIV,&val);
331
332         val = (PLL0_BYPASS) | (PLL0_BYPASS << 16);  //bypass pll0 
333         ret = rk616->write_dev(rk616,CRU_PLL0_CON0,&val);
334
335         val = (PLL1_BYPASS) | (PLL1_BYPASS << 16);
336         ret = rk616->write_dev(rk616,CRU_PLL1_CON0,&val);
337
338         return 0;
339 }
340
341
342 static int rk616_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
343 {
344         int ret;
345         struct mfd_rk616 *rk616 = NULL;
346         struct clk *iis_clk;
347
348         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 
349         {
350                 dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
351                 ret = -ENODEV;
352         }
353         rk616 = kzalloc(sizeof(struct mfd_rk616), GFP_KERNEL);
354         if (rk616 == NULL)
355         {
356                 printk(KERN_ALERT "alloc for struct rk616 fail\n");
357                 ret = -ENOMEM;
358         }
359         
360         rk616->dev = &client->dev;
361         rk616->pdata = client->dev.platform_data;
362         rk616->client = client;
363         i2c_set_clientdata(client, rk616);
364         dev_set_drvdata(rk616->dev,rk616);
365         
366 #if defined(CONFIG_SND_RK29_SOC_I2S_8CH)        
367         iis_clk = clk_get_sys("rk29_i2s.0", "i2s");
368 #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH)
369         iis_clk = clk_get_sys("rk29_i2s.1", "i2s");
370 #else
371         iis_clk = clk_get_sys("rk29_i2s.2", "i2s");
372 #endif
373         if (IS_ERR(iis_clk)) 
374         {
375                 dev_err(&client->dev,"failed to get i2s clk\n");
376                 ret = PTR_ERR(iis_clk);
377         }
378         else
379         {
380                 rk616->mclk = iis_clk;
381                 
382                 #if defined(CONFIG_ARCH_RK29)
383                 rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK);
384                 #else
385                 iomux_set(I2S0_CLK);
386                 #endif
387                 clk_enable(iis_clk);
388                 clk_set_rate(iis_clk, 11289600);
389                 //clk_put(iis_clk);
390         }
391
392         
393         if(rk616->pdata->power_init)
394                 rk616->pdata->power_init();
395         
396         rk616->read_dev = rk616_i2c_read_reg;
397         rk616->write_dev = rk616_i2c_write_reg;
398         
399 #if defined(CONFIG_DEBUG_FS)
400         rk616->debugfs_dir = debugfs_create_dir("rk616", NULL);
401         if (IS_ERR(rk616->debugfs_dir))
402         {
403                 dev_err(rk616->dev,"failed to create debugfs dir for rk616!\n");
404         }
405         else
406                 debugfs_create_file("core", S_IRUSR,rk616->debugfs_dir,rk616,&rk616_reg_fops);
407 #endif
408         rk616_clk_common_init(rk616);
409         ret = mfd_add_devices(rk616->dev, -1,
410                                       rk616_devs, ARRAY_SIZE(rk616_devs),
411                                       NULL, rk616->irq_base);
412         
413         dev_info(&client->dev,"rk616 core probe success!\n");
414         return 0;
415 }
416
417 static int __devexit rk616_i2c_remove(struct i2c_client *client)
418 {
419         return 0;
420 }
421
422 static const struct i2c_device_id id_table[] = {
423         {"rk616", 0 },
424         { }
425 };
426
427 static struct i2c_driver rk616_i2c_driver  = {
428         .driver = {
429                 .name  = "rk616",
430                 .owner = THIS_MODULE,
431         },
432         .probe          = &rk616_i2c_probe,
433         .remove         = &rk616_i2c_remove,
434         .id_table       = id_table,
435 };
436
437
438 static int __init rk616_module_init(void)
439 {
440         return i2c_add_driver(&rk616_i2c_driver);
441 }
442
443 static void __exit rk616_module_exit(void)
444 {
445         i2c_del_driver(&rk616_i2c_driver);
446 }
447
448 subsys_initcall_sync(rk616_module_init);
449 module_exit(rk616_module_exit);
450
451