mfd: Drop unused rk610/rk616 driver

Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
Change-Id: I76c73d0c565b04261a099373c7a9200d6058b8ec
This commit is contained in:
Wyon Bi 2021-09-24 16:12:52 +08:00 committed by Tao Huang
parent c35d2e69de
commit ff9626ac6c
5 changed files with 0 additions and 2375 deletions

View File

@ -1,387 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <asm/gpio.h>
#include <linux/mfd/core.h>
#include <linux/mfd/rk610_core.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#if defined(CONFIG_DEBUG_FS)
#include <linux/fs.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#endif
#define GPIO_HIGH 1
#define GPIO_LOW 0
/*
* Debug
*/
#if 0
#define DBG(x...) printk(KERN_INFO x)
#else
#define DBG(x...)
#endif
static struct i2c_client *rk610_control_client = NULL;
int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
{
struct i2c_adapter *adap=client->adapter;
struct i2c_msg msg;
int ret;
char *tx_buf = (char *)kmalloc(count + 1, GFP_KERNEL);
if(!tx_buf)
return -ENOMEM;
tx_buf[0] = reg;
memcpy(tx_buf+1, buf, count);
msg.addr = client->addr;
msg.flags = client->flags;
msg.len = count + 1;
msg.buf = (char *)tx_buf;
msg.scl_rate = scl_rate;
// msg.udelay = client->udelay;
ret = i2c_transfer(adap, &msg, 1);
kfree(tx_buf);
return (ret == 1) ? count : ret;
}
int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
{
struct i2c_adapter *adap=client->adapter;
struct i2c_msg msgs[2];
int ret;
char reg_buf = reg;
msgs[0].addr = client->addr;
msgs[0].flags = client->flags;
msgs[0].len = 1;
msgs[0].buf = &reg_buf;
msgs[0].scl_rate = scl_rate;
// msgs[0].udelay = client->udelay;
msgs[1].addr = client->addr;
msgs[1].flags = client->flags | I2C_M_RD;
msgs[1].len = count;
msgs[1].buf = (char *)buf;
msgs[1].scl_rate = scl_rate;
// msgs[1].udelay = client->udelay;
ret = i2c_transfer(adap, msgs, 2);
return (ret == 2)? count : ret;
}
static struct mfd_cell rk610_devs[] = {
{
.name = "rk610-lcd",
.id = 0,
},
};
int rk610_control_send_byte(const char reg, const char data)
{
int ret;
DBG("reg = 0x%02x, val=0x%02x\n", reg ,data);
if(rk610_control_client == NULL)
return -1;
//i2c_master_reg8_send
ret = i2c_master_reg8_send(rk610_control_client, reg, &data, 1, 100*1000);
if (ret > 0)
ret = 0;
return ret;
}
#ifdef CONFIG_SND_SOC_RK610
static unsigned int current_pll_value = 0;
int rk610_codec_pll_set(unsigned int rate)
{
char N, M, NO, DIV;
unsigned int F;
char data;
if(current_pll_value == rate)
return 0;
// Input clock is 12MHz.
if(rate == 11289600) {
// For 11.2896MHz, N = 2 M= 75 F = 0.264(0x43958) NO = 8
N = 2;
NO = 3;
M = 75;
F = 0x43958;
DIV = 5;
}
else if(rate == 12288000) {
// For 12.2888MHz, N = 2 M= 75 F = 0.92(0xEB851) NO = 8
N = 2;
NO = 3;
M = 75;
F = 0xEB851;
DIV = 5;
}
else {
printk(KERN_ERR "[%s] not support such frequency\n", __FUNCTION__);
return -1;
}
//Enable codec pll fractional number and power down.
data = 0x00;
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON5, data);
msleep(10);
data = (N << 4) | NO;
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON0, data);
// M
data = M;
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON1, data);
// F
data = F & 0xFF;
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON2, data);
data = (F >> 8) & 0xFF;
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON3, data);
data = (F >> 16) & 0xFF;
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON4, data);
// i2s mclk = codec_pll/5;
i2c_master_reg8_recv(rk610_control_client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000);
data &= ~CLOCK_CON1_I2S_DVIDER_MASK;
data |= (DIV - 1);
rk610_control_send_byte(RK610_CONTROL_REG_CLOCK_CON1, data);
// Power up codec pll.
data |= C_PLL_POWER_ON;
rk610_control_send_byte(RK610_CONTROL_REG_C_PLL_CON5, data);
current_pll_value = rate;
DBG("[%s] rate %u\n", __FUNCTION__, rate);
return 0;
}
void rk610_control_init_codec(void)
{
struct i2c_client *client = rk610_control_client;
char data = 0;
int ret;
if(rk610_control_client == NULL)
return;
DBG("[%s] start\n", __FUNCTION__);
//gpio_set_value(RK610_RESET_PIN, GPIO_LOW); //reset rk601
// mdelay(100);
//gpio_set_value(RK610_RESET_PIN, GPIO_HIGH);
//mdelay(100);
// Set i2c glitch timeout.
data = 0x22;
ret = i2c_master_reg8_send(client, RK610_CONTROL_REG_I2C_CON, &data, 1, 20*1000);
// rk610_codec_pll_set(11289600);
//use internal codec, enable DAC ADC LRCK output.
// i2c_master_reg8_recv(client, RK610_CONTROL_REG_CODEC_CON, &data, 1, 100*1000);
// data = CODEC_CON_BIT_DAC_LRCL_OUTPUT_DISABLE | CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE;
// data = CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE;
data = 0;
rk610_control_send_byte(RK610_CONTROL_REG_CODEC_CON, data);
// Select internal i2s clock from codec_pll.
i2c_master_reg8_recv(rk610_control_client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000);
// data |= CLOCK_CON1_I2S_CLK_CODEC_PLL;
data = 0;
rk610_control_send_byte(RK610_CONTROL_REG_CLOCK_CON1, data);
i2c_master_reg8_recv(client, RK610_CONTROL_REG_CODEC_CON, &data, 1, 100*1000);
DBG("[%s] RK610_CONTROL_REG_CODEC_CON is %x\n", __FUNCTION__, data);
i2c_master_reg8_recv(client, RK610_CONTROL_REG_CLOCK_CON1, &data, 1, 100*1000);
DBG("[%s] RK610_CONTROL_REG_CLOCK_CON1 is %x\n", __FUNCTION__, data);
}
#endif
static int rk610_read_p0_reg(struct i2c_client *client, char reg, char *val)
{
return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
}
static int rk610_write_p0_reg(struct i2c_client *client, char reg, char *val)
{
return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
}
#if defined(CONFIG_DEBUG_FS)
static int rk610_reg_show(struct seq_file *s, void *v)
{
char reg = 0;
u8 val = 0;
struct rk610_core_info *core_info = s->private;
if(!core_info)
{
dev_err(core_info->dev,"no mfd rk610!\n");
return 0;
}
for(reg=C_PLL_CON0;reg<= I2C_CON;reg++)
{
rk610_read_p0_reg(core_info->client, reg, &val);
if(reg%8==0)
seq_printf(s,"\n0x%02x:",reg);
seq_printf(s," %02x",val);
}
seq_printf(s,"\n");
return 0;
}
static ssize_t rk610_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
struct rk610_core_info *core_info = file->f_path.dentry->d_inode->i_private;
u32 reg,val;
char kbuf[25];
if (copy_from_user(kbuf, buf, count))
return -EFAULT;
sscanf(kbuf, "%x%x", &reg,&val);
rk610_write_p0_reg(core_info->client, reg, (u8*)&val);
return count;
}
static int rk610_reg_open(struct inode *inode, struct file *file)
{
struct rk610_core_info *core_info = inode->i_private;
return single_open(file,rk610_reg_show,core_info);
}
static const struct file_operations rk610_reg_fops = {
.owner = THIS_MODULE,
.open = rk610_reg_open,
.read = seq_read,
.write = rk610_reg_write,
.llseek = seq_lseek,
.release = single_release,
};
#endif
static int rk610_control_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct rk610_core_info *core_info = NULL;
struct device_node *rk610_np;
DBG("[%s] start\n", __FUNCTION__);
core_info = kmalloc(sizeof(struct rk610_core_info), GFP_KERNEL);
if(!core_info)
{
dev_err(&client->dev, ">> rk610 core inf kmalloc fail!");
return -ENOMEM;
}
memset(core_info, 0, sizeof(struct rk610_core_info));
rk610_control_client = client;
core_info->client = client;
core_info->dev = &client->dev;
i2c_set_clientdata(client,core_info);
rk610_np = core_info->dev->of_node;
core_info->reset_gpio = of_get_named_gpio(rk610_np,"rk610-reset-io", 0);
if (!gpio_is_valid(core_info->reset_gpio)){
printk("invalid core_info->reset_gpio: %d\n",core_info->reset_gpio);
return -1;
}
ret = gpio_request(core_info->reset_gpio, "rk610-reset-io");
if( ret != 0){
printk("gpio_request core_info->reset_gpio invalid: %d\n",core_info->reset_gpio);
return ret;
}
gpio_direction_output(core_info->reset_gpio, GPIO_HIGH);
msleep(100);
gpio_direction_output(core_info->reset_gpio, GPIO_LOW);
msleep(100);
gpio_set_value(core_info->reset_gpio, GPIO_HIGH);
core_info->i2s_clk= clk_get(&client->dev, "i2s_clk");
if (IS_ERR(core_info->i2s_clk)) {
dev_err(&client->dev, "Can't retrieve i2s clock\n");
ret = PTR_ERR(core_info->i2s_clk);
return ret;
}
clk_set_rate(core_info->i2s_clk, 11289600);
clk_prepare_enable(core_info->i2s_clk);
ret = mfd_add_devices(&client->dev, -1,
rk610_devs, ARRAY_SIZE(rk610_devs),
NULL,0,NULL);
#if defined(CONFIG_DEBUG_FS)
core_info->debugfs_dir = debugfs_create_dir("rk610", NULL);
if (IS_ERR(core_info->debugfs_dir))
{
dev_err(&client->dev,"failed to create debugfs dir for rk610!\n");
}
else
debugfs_create_file("core", S_IRUSR,core_info->debugfs_dir,core_info,&rk610_reg_fops);
#endif
return 0;
}
static int rk610_control_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id rk610_control_id[] = {
{ "rk610_ctl", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rk610_control_id);
static struct i2c_driver rk610_control_driver = {
.driver = {
.name = "rk610_ctl",
},
.probe = rk610_control_probe,
.remove = rk610_control_remove,
.id_table = rk610_control_id,
};
static int __init rk610_control_init(void)
{
return i2c_add_driver(&rk610_control_driver);
}
static void __exit rk610_control_exit(void)
{
i2c_del_driver(&rk610_control_driver);
}
subsys_initcall_sync(rk610_control_init);
module_exit(rk610_control_exit);
MODULE_DESCRIPTION("RK610 control driver");
MODULE_AUTHOR("Rock-chips, <www.rock-chips.com>");
MODULE_LICENSE("GPL");

View File

@ -1,712 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
#include <linux/mfd/rk616.h>
//#include <mach/iomux.h>
#include <linux/err.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#if defined(CONFIG_DEBUG_FS)
#include <linux/fs.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#endif
#if defined(RK616_MIPI_DSI)
#include "../video/rockchip/transmitter/rk616_mipi_dsi.h"
#endif
#ifndef MHZ
#define MHZ (1000*1000)
#endif
static struct mfd_cell rk616_devs[] = {
{
.name = "rk616-lvds",
.id = 0,
},
{
.name = "rk616-codec",
.id = 1,
},
{
.name = "rk616-hdmi",
.id = 2,
},
{
.name = "rk616-mipi",
.id = 3,
},
};
extern int rk_mipi_dsi_init_lite(void);
void rk616_mclk_set_rate(struct clk *mclk,unsigned long rate)
{
clk_set_rate(mclk, rate);
}
static int rk616_i2c_read_reg(struct mfd_rk616 *rk616, u16 reg,u32 *pval)
{
struct i2c_client * client = rk616->client;
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msgs[2];
int ret;
char reg_buf[2];
memcpy(reg_buf, &reg, 2);
msgs[0].addr = client->addr;
msgs[0].flags = client->flags;
msgs[0].len = 2;
msgs[0].buf = reg_buf;
msgs[0].scl_rate = rk616->pdata->scl_rate;
//msgs[0].udelay = client->udelay;
msgs[1].addr = client->addr;
msgs[1].flags = client->flags | I2C_M_RD;
msgs[1].len = 4;
msgs[1].buf = (char *)pval;
msgs[1].scl_rate = rk616->pdata->scl_rate;
//msgs[1].udelay = client->udelay;
ret = i2c_transfer(adap, msgs, 2);
return (ret == 2)? 4 : ret;
}
static int rk616_i2c_write_reg(struct mfd_rk616 *rk616, u16 reg,u32 *pval)
{
struct i2c_client *client = rk616->client;
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msg;
int ret;
char *tx_buf = (char *)kmalloc(6, GFP_KERNEL);
if(!tx_buf)
return -ENOMEM;
memcpy(tx_buf, &reg, 2);
memcpy(tx_buf+2, (char *)pval, 4);
msg.addr = client->addr;
msg.flags = client->flags;
msg.len = 6;
msg.buf = (char *)tx_buf;
msg.scl_rate = rk616->pdata->scl_rate;
//msg.udelay = client->udelay;
ret = i2c_transfer(adap, &msg, 1);
kfree(tx_buf);
return (ret == 1) ? 4 : ret;
}
static int rk616_i2c_write_bits(struct mfd_rk616 *rk616, u16 reg,u32 mask,u32 *pval)
{
struct i2c_client *client = rk616->client;
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msg;
int ret;
u32 reg_val;
char *tx_buf = NULL;
tx_buf = (char *)kmalloc(6, GFP_KERNEL);
if(!tx_buf)
return -ENOMEM;
mutex_lock(&rk616->reg_lock);
rk616->read_dev(rk616,reg,&reg_val);
reg_val &= ~mask;
*pval &= mask;
reg_val |= *pval;
*pval = reg_val;
memcpy(tx_buf, &reg, 2);
memcpy(tx_buf+2, (char *)pval, 4);
msg.addr = client->addr;
msg.flags = client->flags;
msg.len = 6;
msg.buf = (char *)tx_buf;
msg.scl_rate = rk616->pdata->scl_rate;
//msg.udelay = client->udelay;
ret = i2c_transfer(adap, &msg, 1);
kfree(tx_buf);
mutex_unlock(&rk616->reg_lock);
return (ret == 1) ? 4 : ret;
}
static int rk616_i2c_bulk_write(struct mfd_rk616 *rk616, u16 reg,int count,u32 *pval)
{
const struct i2c_client *client = rk616->client;
struct i2c_adapter *adap=client->adapter;
struct i2c_msg msg;
int ret;
char *tx_buf = (char *)kmalloc((count<<2) + 2, GFP_KERNEL);
if(!tx_buf)
return -ENOMEM;
memcpy(tx_buf, &reg, 2);
memcpy(tx_buf+2, (char *)pval, count<<2);
msg.addr = client->addr;
msg.flags = client->flags;
msg.len = (count<<2) + 2;
msg.buf = (char *)tx_buf;
msg.scl_rate = rk616->pdata->scl_rate;
//msg.udelay = client->udelay;
ret = i2c_transfer(adap, &msg, 1);
kfree(tx_buf);
return (ret == 1) ? count : ret;
}
#if defined(CONFIG_DEBUG_FS)
static int rk616_reg_show(struct seq_file *s, void *v)
{
int i = 0;
u32 val = 0;
struct mfd_rk616 *rk616 = s->private;
if(!rk616)
{
dev_err(rk616->dev,"no mfd rk616!\n");
return 0;
}
for(i=0;i<= CRU_CFGMISC_CON;i+=4)
{
rk616->read_dev(rk616,i,&val);
if(i%16==0)
seq_printf(s,"\n0x%04x:",i);
seq_printf(s," %08x",val);
}
seq_printf(s,"\n");
return 0;
}
static ssize_t rk616_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
struct mfd_rk616 *rk616 = file->f_path.dentry->d_inode->i_private;
u32 reg;
u32 val;
char kbuf[25];
if (copy_from_user(kbuf, buf, count))
return -EFAULT;
sscanf(kbuf, "%x%x", &reg,&val);
rk616->write_dev(rk616,reg,&val);
return count;
}
static int rk616_reg_open(struct inode *inode, struct file *file)
{
struct mfd_rk616 *rk616 = inode->i_private;
return single_open(file,rk616_reg_show,rk616);
}
static const struct file_operations rk616_reg_fops = {
.owner = THIS_MODULE,
.open = rk616_reg_open,
.read = seq_read,
.write = rk616_reg_write,
.llseek = seq_lseek,
.release = single_release,
};
#endif
static u32 rk616_clk_gcd(u32 numerator, u32 denominator)
{
u32 a, b;
if (!numerator || !denominator)
return 0;
if (numerator > denominator) {
a = numerator;
b = denominator;
} else {
a = denominator;
b = numerator;
}
while (b != 0) {
int r = b;
b = a % b;
a = r;
}
return a;
}
static int rk616_pll_par_calc(u32 fin_hz,u32 fout_hz,u32 *refdiv, u32 *fbdiv,
u32 *postdiv1, u32 *postdiv2, u32 *frac)
{
// FIXME set postdiv1/2 always 1
u32 gcd;
u64 fin_64, frac_64;
u32 f_frac;
if(!fin_hz || !fout_hz)
return -EINVAL;
if(fin_hz / MHZ * MHZ == fin_hz && fout_hz /MHZ * MHZ == fout_hz)
{
fin_hz /= MHZ;
fout_hz /= MHZ;
gcd = rk616_clk_gcd(fin_hz, fout_hz);
*refdiv = fin_hz / gcd;
*fbdiv = fout_hz / gcd;
*postdiv1 = 1;
*postdiv2 = 1;
*frac = 0;
}
else
{
gcd = rk616_clk_gcd(fin_hz / MHZ, fout_hz / MHZ);
*refdiv = fin_hz / MHZ / gcd;
*fbdiv = fout_hz / MHZ / gcd;
*postdiv1 = 1;
*postdiv2 = 1;
*frac = 0;
f_frac = (fout_hz % MHZ);
fin_64 = fin_hz;
do_div(fin_64, (u64)*refdiv);
frac_64 = (u64)f_frac << 24;
do_div(frac_64, fin_64);
*frac = (u32) frac_64;
printk(KERN_INFO "frac_64=%llx, frac=%u\n", frac_64, *frac);
}
printk(KERN_INFO "fin=%u,fout=%u,gcd=%u,refdiv=%u,fbdiv=%u,postdiv1=%u,postdiv2=%u,frac=%u\n",
fin_hz, fout_hz, gcd, *refdiv, *fbdiv, *postdiv1, *postdiv2, *frac);
return 0;
}
static int rk616_pll_wait_lock(struct mfd_rk616 *rk616,int id)
{
u32 delay = 10;
u32 val = 0;
int ret;
int offset;
if(id == 0) //PLL0
{
offset = 0;
}
else // PLL1
{
offset = 0x0c;
}
while (delay >= 1)
{
ret = rk616->read_dev(rk616,CRU_PLL0_CON1 + offset,&val);
if (val&PLL0_LOCK)
{
rk616_dbg(rk616->dev,"PLL%d locked\n",id);
break;
}
msleep(1);
delay--;
}
if (delay == 0)
{
dev_err(rk616->dev,"rk616 wait PLL%d lock time out!\n",id);
}
return 0;
}
int rk616_pll_pwr_down(struct mfd_rk616 *rk616,int id)
{
u32 val = 0;
int ret;
int offset;
if(id == 0) //PLL0
{
offset = 0;
}
else // PLL1
{
offset = 0x0c;
}
val = PLL0_PWR_DN | (PLL0_PWR_DN << 16);
ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
return 0;
}
int rk616_pll_set_rate(struct mfd_rk616 *rk616,int id,u32 cfg_val,u32 frac)
{
u32 val = 0;
int ret;
int offset;
u16 con0 = cfg_val & 0xffff;
u16 con1 = (cfg_val >> 16)&0xffff;
u32 fbdiv = con0 & 0xfff;
u32 postdiv1 = (con0 >> 12)&0x7;
u32 refdiv = con1 & 0x3f;
u32 postdiv2 = (con1 >> 6) & 0x7;
u8 mode = !frac;
if(id == 0) //PLL0
{
if(((rk616->pll0_rate >> 32) == cfg_val) &&
((rk616->pll0_rate & 0xffffffff) == frac))
{
//return 0;
}
rk616->pll0_rate = ((u64)cfg_val << 32) | frac;
offset = 0;
}
else // PLL1
{
if(((rk616->pll1_rate >> 32) == cfg_val) &&
((rk616->pll1_rate & 0xffffffff) == frac))
{
// return 0;
}
rk616->pll1_rate = ((u64)cfg_val << 32) | frac;
offset = 0x0c;
}
val = PLL0_PWR_DN | (PLL0_PWR_DN << 16);
ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
ret = rk616->read_dev(rk616,CRU_PLL0_CON2 + offset,&val);
val &= 0xff000000;
if(frac)
val |= PLL0_FRAC(frac);
else
val |= 0x800000; //default value
ret = rk616->write_dev(rk616,CRU_PLL0_CON2 + offset,&val);
val = PLL0_POSTDIV1(postdiv1) | PLL0_FBDIV(fbdiv) | PLL0_POSTDIV1_MASK |
PLL0_FBDIV_MASK | (PLL0_BYPASS << 16);
ret = rk616->write_dev(rk616,CRU_PLL0_CON0 + offset,&val);
val = PLL0_DIV_MODE(mode) | PLL0_POSTDIV2(postdiv2) | PLL0_REFDIV(refdiv) |
(PLL0_DIV_MODE_MASK) | PLL0_POSTDIV2_MASK | PLL0_REFDIV_MASK;
ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
val = (PLL0_PWR_DN << 16);
ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
rk616_pll_wait_lock(rk616,id);
msleep(5);
return 0;
}
/***********************************
default clk patch settiing:
CLKIN-------->CODEC
LCD_DCLK0--->PLL0--->Dither--->LVDS/MIPI
LCD_DCLK1--->PLL1--->HDMI
************************************/
static int rk616_clk_common_init(struct mfd_rk616 *rk616)
{
u32 val = 0;
int ret;
val = PLL1_CLK_SEL(LCD1_DCLK) | PLL0_CLK_SEL(LCD0_DCLK) | LCD1_CLK_DIV(0) |
LCD0_CLK_DIV(0) | PLL1_CLK_SEL_MASK | PLL0_CLK_SEL_MASK |
LCD1_CLK_DIV_MASK | LCD0_CLK_DIV_MASK; //pll1 clk from lcdc1_dclk,pll0 clk from lcdc0_dclk,mux_lcdx = lcdx_clk
ret = rk616->write_dev(rk616,CRU_CLKSEL0_CON,&val);
val = SCLK_SEL(SCLK_SEL_PLL1) | CODEC_MCLK_SEL(CODEC_MCLK_SEL_12M) |
CODEC_MCLK_SEL_MASK | SCLK_SEL_MASK; //codec mclk from clkin
ret = rk616->write_dev(rk616,CRU_CLKSEL1_CON,&val);
val = 0; //codec mck = clkin
ret = rk616->write_dev(rk616,CRU_CODEC_DIV,&val);
val = (PLL0_BYPASS) | (PLL0_BYPASS << 16); //bypass pll0
ret = rk616->write_dev(rk616,CRU_PLL0_CON0,&val);
val = PLL0_PWR_DN | (PLL0_PWR_DN << 16);
ret = rk616->write_dev(rk616,CRU_PLL0_CON1,&val); //power down pll0
val = (PLL1_BYPASS) | (PLL1_BYPASS << 16);
ret = rk616->write_dev(rk616,CRU_PLL1_CON0,&val);
return 0;
}
static int rk616_core_suspend(struct device *dev, pm_message_t state)
{
return 0;
}
static int rk616_core_resume(struct device* dev)
{
struct mfd_rk616 *rk616 = dev_get_drvdata(dev);
rk616_clk_common_init(rk616);
return 0;
}
/*
dts:
/include/ "rk616.dtsi"
&rk616 {
rk616,scl_rate = <100000>;
rk616,lcd0_func = <1>;
rk616,lcd1_func = <1>;
rk616,lvds_ch_nr = <1>;
rk616,hdmi_irq_gpio = <&gpio2 GPIO_D6 1>;
rk616-codec {
spk-ctl-gpio = <&gpio2 GPIO_D7 GPIO_ACTIVE_HIGH>;
hp-ctl-gpio = <&gpio2 GPIO_D7 GPIO_ACTIVE_HIGH>;
//rcv-ctl-gpio = <&gpio2 GPIO_D7 GPIO_ACTIVE_HIGH>;
//mic-sel-gpio = <&gpio2 GPIO_D7 GPIO_ACTIVE_HIGH>;
//delay for MOSFET or SPK power amplifier chip(ms)
spk-amplifier-delay = <150>;
hp-mosfet-delay = <50>;
//hp-mic-capture-from-linein; //If hpmic is connected to linein, set this.
//hp-mic-capture-from-mic2in; //If hpmic is connected to mic2, set this.
//virtual-hp-gnd; //If hp gnd is not connected to gnd(0V), set this.
//volume setting: 0 ~ 31, -18dB ~ 28.5dB, Step: 1.5dB
skp-volume = <24>;
hp-volume = <24>;
capture-volume = <24>;
};
power_ctr: rk616_power_ctr {
rk616_pwren: rk616_pwren {
rockchip,power_type = <GPIO>;
gpios = <&gpio0 GPIO_A3 GPIO_ACTIVE_HIGH>;
rockchip,delay = <0>;
};
rk616_rst: rk616_rst {
rockchip,power_type = <GPIO>;
gpios = <&gpio3 GPIO_B2 GPIO_ACTIVE_HIGH>;
rockchip,delay = <10>;
};
};
};
*/
#ifdef CONFIG_OF
static struct rk616_platform_data *rk616_parse_dt(struct mfd_rk616 *rk616)
{
struct rk616_platform_data *pdata = NULL;
struct device_node *rk616_np = rk616->dev->of_node;
int val = 0,gpio = 0;
if (!rk616_np) {
printk("could not find rk616 node\n");
return NULL;
}
pdata = devm_kzalloc(rk616->dev, sizeof(struct rk616_platform_data), GFP_KERNEL);
if (!pdata) {
dev_err(rk616->dev, "rk616_platform_data kmalloc fail!");
return NULL;
}
if(!of_property_read_u32(rk616_np, "rk616,scl_rate", &val))
pdata->scl_rate = val;
if(!of_property_read_u32(rk616_np, "rk616,lcd0_func", &val))
pdata->lcd0_func = val;
if(!of_property_read_u32(rk616_np, "rk616,lcd1_func", &val))
pdata->lcd1_func = val;
if(!of_property_read_u32(rk616_np, "rk616,lvds_ch_nr", &val))
pdata->lvds_ch_nr = val;
gpio = of_get_named_gpio(rk616_np,"rk616,hdmi_irq_gpio", 0);
if (!gpio_is_valid(gpio))
printk("invalid hdmi_irq_gpio: %d\n",gpio);
pdata->hdmi_irq = gpio;
//TODO Daisen >>pwr gpio wait to add
return pdata;
}
#else
static struct rk616_platform_data *rk616_parse_dt(struct mfd_rk616 *rk616)
{
return NULL;
}
#endif
#if defined(CONFIG_OF)
static const struct of_device_id rk616_dt_ids[] = {
{.compatible = "rockchip,rk616",},
{}
};
MODULE_DEVICE_TABLE(of, rk616_dt_ids);
#endif
static int rk616_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
int ret;
struct mfd_rk616 *rk616 = NULL;
struct clk *iis_clk;
if (client->dev.of_node) {
if (!of_match_device(rk616_dt_ids, &client->dev)) {
dev_err(&client->dev, "Failed to find matching dt id\n");
return -EINVAL;
}
}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
{
dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
ret = -ENODEV;
}
rk616 = kzalloc(sizeof(struct mfd_rk616), GFP_KERNEL);
if (rk616 == NULL)
{
printk(KERN_ALERT "alloc for struct rk616 fail\n");
ret = -ENOMEM;
}
rk616->dev = &client->dev;
rk616->pdata = rk616_parse_dt(rk616);
rk616->client = client;
i2c_set_clientdata(client, rk616);
dev_set_drvdata(rk616->dev,rk616);
#if defined(CONFIG_SND_RK29_SOC_I2S_8CH)
iis_clk = clk_get_sys("rk29_i2s.0", "i2s");
#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH)
iis_clk = clk_get_sys("rk29_i2s.1", "i2s");
#else
iis_clk = clk_get_sys("rk29_i2s.2", "i2s");
#endif
if (IS_ERR(iis_clk))
{
dev_err(&client->dev,"failed to get i2s clk\n");
ret = PTR_ERR(iis_clk);
}
else
{
rk616->mclk = iis_clk;
#if defined(CONFIG_ARCH_RK29)
rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK);
#else
//iomux_set(I2S0_MCLK); //set at i2s driver
#endif
clk_enable(iis_clk);
//clk_set_rate(iis_clk, 11289600);
rk616_mclk_set_rate(iis_clk,11289600);
//clk_put(iis_clk);
}
mutex_init(&rk616->reg_lock);
if(rk616->pdata->power_init)
rk616->pdata->power_init();
rk616->read_dev = rk616_i2c_read_reg;
rk616->write_dev = rk616_i2c_write_reg;
rk616->write_dev_bits = rk616_i2c_write_bits;
rk616->write_bulk = rk616_i2c_bulk_write;
#if defined(CONFIG_DEBUG_FS)
rk616->debugfs_dir = debugfs_create_dir("rk616", NULL);
if (IS_ERR(rk616->debugfs_dir))
{
dev_err(rk616->dev,"failed to create debugfs dir for rk616!\n");
}
else
debugfs_create_file("core", S_IRUSR,rk616->debugfs_dir,rk616,&rk616_reg_fops);
#endif
rk616_clk_common_init(rk616);
ret = mfd_add_devices(rk616->dev, -1,
rk616_devs, ARRAY_SIZE(rk616_devs),
NULL, rk616->irq_base, NULL);
dev_info(&client->dev,"rk616 core probe success!\n");
return 0;
}
static int rk616_i2c_remove(struct i2c_client *client)
{
return 0;
}
static void rk616_core_shutdown(struct i2c_client *client)
{
struct mfd_rk616 *rk616 = i2c_get_clientdata(client);
if(rk616->pdata->power_deinit)
rk616->pdata->power_deinit();
}
static const struct i2c_device_id id_table[] = {
{"rk616", 0 },
{ }
};
static struct i2c_driver rk616_i2c_driver = {
.driver = {
.name = "rk616",
.owner = THIS_MODULE,
.suspend = &rk616_core_suspend,
.resume = &rk616_core_resume,
.of_match_table = of_match_ptr(rk616_dt_ids),
},
.probe = &rk616_i2c_probe,
.remove = &rk616_i2c_remove,
.shutdown = &rk616_core_shutdown,
.id_table = id_table,
};
static int __init rk616_module_init(void)
{
return i2c_add_driver(&rk616_i2c_driver);
}
static void __exit rk616_module_exit(void)
{
i2c_del_driver(&rk616_i2c_driver);
}
subsys_initcall_sync(rk616_module_init);
module_exit(rk616_module_exit);

View File

@ -1,826 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mfd/rk616.h>
extern int rk616_pll_set_rate(struct mfd_rk616 *rk616,int id,u32 cfg_val,u32 frac);
extern int rk616_pll_pwr_down(struct mfd_rk616 *rk616,int id);
/*rk616 video interface config*/
int rk616_vif_disable(struct mfd_rk616 *rk616,int id)
{
u32 val = 0;
int ret = 0;
if(id == 0) //video interface 0
{
val = (VIF0_EN << 16); //disable vif0
ret = rk616->write_dev(rk616,VIF0_REG0,&val);
}
else //vide0 interface 1
{
val = (VIF0_EN << 16); //disabl VIF1
ret = rk616->write_dev(rk616,VIF1_REG0,&val);
}
msleep(21);
if(id == 0) //video interface 0
{
val = VIF0_CLK_GATE | (VIF0_CLK_GATE << 16); //gating vif0
ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
}
else //vide0 interface 1
{
val = VIF1_CLK_GATE | (VIF1_CLK_GATE << 16); //gating vif1
ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
}
rk616_dbg(rk616->dev,"rk616 vif%d disable\n",id);
return 0;
}
int rk616_vif_enable(struct mfd_rk616 *rk616,int id)
{
u32 val = 0;
u32 offset = 0;
int ret;
if(id == 0)
{
val = (VIF0_CLK_BYPASS << 16) | (VIF0_CLK_GATE << 16);
offset = 0;
}
else
{
val = (VIF1_CLK_BYPASS << 16) |(VIF1_CLK_GATE << 16);
offset = 0x18;
}
ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
val = 0;
val |= (VIF0_DDR_CLK_EN <<16) | (VIF0_DDR_PHASEN_EN << 16) | (VIF0_DDR_MODE_EN << 16)|
(VIF0_EN <<16) | VIF0_EN; //disable ddr mode,enable VIF
ret = rk616->write_dev(rk616,VIF0_REG0 + offset,&val);
rk616_dbg(rk616->dev,"rk616 vif%d enable\n",id);
return 0;
}
static int rk616_vif_bypass(struct mfd_rk616 *rk616,int id)
{
u32 val = 0;
int ret;
if(id == 0)
{
val = (VIF0_CLK_BYPASS | VIF0_CLK_BYPASS << 16);
}
else
{
val = (VIF1_CLK_BYPASS | VIF1_CLK_BYPASS << 16);
}
ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
rk616_dbg(rk616->dev,"rk616 vif%d bypass\n",id);
return 0;
}
static bool pll_sel_mclk12m(struct mfd_rk616 *rk616,int pll_id)
{
if(pll_id == 0) //pll0
{
if(rk616->route.pll0_clk_sel == PLL0_CLK_SEL(MCLK_12M))
return true;
else
return false;
}
else
{
if(rk616->route.pll1_clk_sel == PLL1_CLK_SEL(MCLK_12M))
return true;
else
return false;
}
return false;
}
int rk616_vif_cfg(struct mfd_rk616 *rk616,struct rk_screen *screen,int id)
{
int ret = 0;
u32 val = 0;
int offset = 0;
int pll_id;
bool pll_use_mclk12m = false;
if(id == 0) //video interface 0
{
if(!rk616->route.vif0_en)
{
rk616_vif_disable(rk616,id);
return 0;
}
offset = 0;
pll_id = rk616->route.vif0_clk_sel;
}
else //vide0 interface 1
{
if(!rk616->route.vif1_en)
{
rk616_vif_disable(rk616,id);
return 0;
}
offset = 0x18;
pll_id = (rk616->route.vif1_clk_sel >> 6);
}
pll_use_mclk12m = pll_sel_mclk12m(rk616,pll_id);
if(pll_use_mclk12m)
{
//clk_set_rate(rk616->mclk, 12000000);
rk616_mclk_set_rate(rk616->mclk,12000000);
}
if(!screen)
{
dev_err(rk616->dev,"%s:screen is null.........\n",__func__);
return -EINVAL;
}
rk616_vif_disable(rk616,id);
if( (screen->mode.xres == 1920) && (screen->mode.yres == 1080))
{
if(pll_use_mclk12m)
//rk616_pll_set_rate(rk616,pll_id,0xc11025,0x200000);
rk616_pll_set_rate(rk616,pll_id,0x028853de,0);
else
rk616_pll_set_rate(rk616,pll_id,0x02bf5276,0);
val = (0xc1) | (0x01 <<16);
}
else if((screen->mode.xres == 1280) && (screen->mode.yres == 720))
{
if(pll_use_mclk12m)
//rk616_pll_set_rate(rk616,pll_id,0x01811025,0x200000);
rk616_pll_set_rate(rk616,pll_id,0x0288418c,0);
else
rk616_pll_set_rate(rk616,pll_id,0x1422014,0);
val = (0xc1) | (0x01 <<16);
}
else if((screen->mode.xres == 720))
{
if(pll_use_mclk12m )
{
rk616_pll_set_rate(rk616,pll_id,0x0306510e,0);
}
else
rk616_pll_set_rate(rk616,pll_id,0x1c13015,0);
val = (0x1) | (0x01 <<16);
}
ret = rk616->write_dev(rk616,VIF0_REG1 + offset,&val);
val = (screen->mode.hsync_len << 16) | (screen->mode.hsync_len + screen->mode.left_margin +
screen->mode.right_margin + screen->mode.xres);
ret = rk616->write_dev(rk616,VIF0_REG2 + offset,&val);
val = ((screen->mode.hsync_len + screen->mode.left_margin + screen->mode.xres)<<16) |
(screen->mode.hsync_len + screen->mode.left_margin);
ret = rk616->write_dev(rk616,VIF0_REG3 + offset,&val);
val = (screen->mode.vsync_len << 16) | (screen->mode.vsync_len + screen->mode.upper_margin +
screen->mode.lower_margin + screen->mode.yres);
ret = rk616->write_dev(rk616,VIF0_REG4 + offset,&val);
val = ((screen->mode.vsync_len + screen->mode.upper_margin + screen->mode.yres)<<16) |
(screen->mode.vsync_len + screen->mode.upper_margin);
ret = rk616->write_dev(rk616,VIF0_REG5 + offset,&val);
if(id == 0)
{
val = VIF0_SYNC_EN | (VIF0_SYNC_EN << 16);
rk616->write_dev(rk616,CRU_IO_CON0,&val);
}
else
{
val = VIF1_SYNC_EN | (VIF1_SYNC_EN << 16);
rk616->write_dev(rk616,CRU_IO_CON0,&val);
}
rk616_vif_enable(rk616,id);
return ret;
}
static int rk616_scaler_disable(struct mfd_rk616 *rk616)
{
u32 val = 0;
int ret;
val &= (~SCL_EN); //disable scaler
val |= (SCL_EN<<16);
ret = rk616->write_dev(rk616,SCL_REG0,&val);
rk616_dbg(rk616->dev,"rk616 scaler disable\n");
return 0;
}
int rk616_scaler_cfg(struct mfd_rk616 *rk616,struct rk_screen *screen)
{
u32 scl_hor_mode,scl_ver_mode;
u32 scl_v_factor,scl_h_factor;
u32 scl_reg0_value,scl_reg1_value,scl_reg2_value; //scl_con,scl_h_factor,scl_v_factor,
u32 scl_reg3_value,scl_reg4_value,scl_reg5_value,scl_reg6_value; //dsp_frame_hst,dsp_frame_vst,dsp_timing,dsp_act_timing
u32 scl_reg7_value,scl_reg8_value; //dsp_hbor ,dsp_vbor
u32 dst_frame_hst,dst_frame_vst; //时序缓存
u32 dst_vact_st;
u32 dsp_htotal,dsp_hs_end,dsp_hact_st,dsp_hact_end; //scaler输出的timing参数
u32 dsp_vtotal,dsp_vs_end,dsp_vact_st,dsp_vact_end;
u32 dsp_hbor_end,dsp_hbor_st,dsp_vbor_end,dsp_vbor_st;
u32 src_w,src_h,src_htotal,dst_w,dst_h,src_vact_st;
u16 bor_right = 0;
u16 bor_left = 0;
u16 bor_up = 0;
u16 bor_down = 0;
u8 hor_down_mode = 0; //1:average,0:bilinear
u8 ver_down_mode = 0;
u8 bic_coe_sel = 2;
struct rk_screen *src;
struct rk_screen *dst;
int pll_id;
struct rk616_route *route = &rk616->route;
if(!route->scl_en)
{
rk616_scaler_disable(rk616);
return 0;
}
dst = screen;
if(!dst)
{
dev_err(rk616->dev,"%s:screen is null!\n",__func__);
return -EINVAL;
}
if(route->scl_bypass)
{
src = dst;
dst->pll_cfg_val = 0x01422014;
dst->frac = 0;
}
else
src = screen->ext_screen;
if(route->sclk_sel == SCLK_SEL(SCLK_SEL_PLL0))
pll_id = 0;
else
pll_id = 1;
rk616_scaler_disable(rk616);
rk616_pll_set_rate(rk616,pll_id,dst->pll_cfg_val,dst->frac);
dst_frame_vst = dst->scl_vst;
dst_frame_hst = dst->scl_hst;
#if 1
src_htotal = src->mode.hsync_len + src->mode.left_margin + src->mode.xres + src->mode.right_margin;
src_vact_st = src->mode.vsync_len + src->mode.upper_margin ;
dst_vact_st = dst->mode.vsync_len + dst->mode.upper_margin;
dsp_htotal = dst->mode.hsync_len + dst->mode.left_margin + dst->mode.xres + dst->mode.right_margin; //dst_htotal ;
dsp_hs_end = dst->mode.hsync_len;
dsp_vtotal = dst->mode.vsync_len + dst->mode.upper_margin + dst->mode.yres + dst->mode.lower_margin;
dsp_vs_end = dst->mode.vsync_len;
dsp_hbor_end = dst->mode.hsync_len + dst->mode.left_margin + dst->mode.xres;
dsp_hbor_st = dst->mode.hsync_len + dst->mode.left_margin ;
dsp_vbor_end = dst->mode.vsync_len + dst->mode.upper_margin + dst->mode.yres; //dst_vact_end ;
dsp_vbor_st = dst_vact_st ;
dsp_hact_st = dsp_hbor_st + bor_left;
dsp_hact_end = dsp_hbor_end - bor_right;
dsp_vact_st = dsp_vbor_st + bor_up;
dsp_vact_end = dsp_vbor_end - bor_down;
src_w = src->mode.xres;
src_h = src->mode.yres;
dst_w = dsp_hact_end - dsp_hact_st ;
dst_h = dsp_vact_end - dsp_vact_st ;
if(src_w > dst_w) //判断hor的缩放模式 0no_scl 1scl_up 2scl_down
{
scl_hor_mode = 0x2; //scl_down
if(hor_down_mode == 0)//bilinear
{
if((src_w-1)/(dst_w-1) > 2)
{
scl_h_factor = ((src_w-1)<<14)/(dst_w-1);
}
else
scl_h_factor = ((src_w-2)<<14)/(dst_w-1);
}
else //average
{
scl_h_factor = ((dst_w)<<16)/(src_w-1);
}
}
else if(src_w == dst_w)
{
scl_hor_mode = 0x0; //no_Scl
scl_h_factor = 0x0;
}
else
{
scl_hor_mode = 0x1; //scl_up
scl_h_factor = ((src_w-1)<<16)/(dst_w-1);
}
if(src_h > dst_h) //判断ver的缩放模式 0no_scl 1scl_up 2scl_down
{
scl_ver_mode = 0x2; //scl_down
if(ver_down_mode == 0)//bilinearhor_down_mode,u8 ver_down_mode
{
if((src_h-1)/(dst_h-1) > 2)
{
scl_v_factor = ((src_h-1)<<14)/(dst_h-1);
}
else
scl_v_factor = ((src_h-2)<<14)/(dst_h-1);
}
else
{
scl_v_factor = ((dst_h)<<16)/(src_h-1);
}
}
else if(src_h == dst_h)
{
scl_ver_mode = 0x0; //no_Scl
scl_v_factor = 0x0;
}
else
{
scl_ver_mode = 0x1; //scl_up
scl_v_factor = ((src_h-1)<<16)/(dst_h-1);
}
//control register0
scl_reg0_value = (0x1ff<<16) | SCL_EN | (scl_hor_mode<<1) |
(scl_ver_mode<<3) | (bic_coe_sel<<5) |
(hor_down_mode<<7) | (ver_down_mode<<8) ;
//factor register1
scl_reg1_value = (scl_v_factor << 16) | scl_h_factor ;
//dsp_frame register2
scl_reg2_value = dst_frame_vst<<16 | dst_frame_hst ;
//dsp_h register3
scl_reg3_value = dsp_hs_end<<16 | dsp_htotal ;
//dsp_hact register4
scl_reg4_value = dsp_hact_end <<16 | dsp_hact_st ;
//dsp_v register5
scl_reg5_value = dsp_vs_end<<16 | dsp_vtotal ;
//dsp_vact register6
scl_reg6_value = dsp_vact_end<<16 | dsp_vact_st ;
//hbor register7
scl_reg7_value = dsp_hbor_end<<16 | dsp_hbor_st ;
//vbor register8
scl_reg8_value = dsp_vbor_end<<16 | dsp_vbor_st ;
rk616->write_dev(rk616,SCL_REG1,&scl_reg1_value);
rk616->write_dev(rk616,SCL_REG2,&scl_reg2_value);
rk616->write_dev(rk616,SCL_REG3,&scl_reg3_value);
rk616->write_dev(rk616,SCL_REG4,&scl_reg4_value);
rk616->write_dev(rk616,SCL_REG5,&scl_reg5_value);
rk616->write_dev(rk616,SCL_REG6,&scl_reg6_value);
rk616->write_dev(rk616,SCL_REG7,&scl_reg7_value);
rk616->write_dev(rk616,SCL_REG8,&scl_reg8_value);
rk616->write_dev(rk616,SCL_REG0,&scl_reg0_value);
rk616_dbg(rk616->dev,"rk616 scaler enable\n");
#endif
return 0;
}
static int rk616_dual_input_cfg(struct mfd_rk616 *rk616,struct rk_screen *screen,
bool enable)
{
struct rk616_platform_data *pdata = rk616->pdata;
struct rk616_route *route = &rk616->route;
route->vif0_bypass = VIF0_CLK_BYPASS;
route->vif0_en = 0;
route->vif0_clk_sel = VIF0_CLKIN_SEL(VIF_CLKIN_SEL_PLL0);
route->pll0_clk_sel = PLL0_CLK_SEL(LCD0_DCLK);
#if defined(CONFIG_RK616_USE_MCLK_12M)
route->pll1_clk_sel = PLL1_CLK_SEL(MCLK_12M);
#else
route->pll1_clk_sel = PLL1_CLK_SEL(LCD1_DCLK);
#endif
route->vif1_clk_sel = VIF1_CLKIN_SEL(VIF_CLKIN_SEL_PLL1);
route->hdmi_sel = HDMI_IN_SEL(HDMI_IN_SEL_VIF1);
route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF1);
if(enable) //hdmi plug in
{
route->vif1_bypass = 0;
route->vif1_en = 1;
}
else //hdmi plug out
{
route->vif1_bypass = VIF1_CLK_BYPASS;
route->vif1_en = 0;
}
route->sclin_sel = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
route->scl_en = 0; //dual lcdc, scaler not needed
route->dither_sel = DITHER_IN_SEL(DITHER_SEL_VIF0); //dither from vif0
route->lcd1_input = 1;
if(screen->type == SCREEN_RGB)
{
route->lvds_en = 1;
route->lvds_mode = RGB; //rgb output
}
else if(screen->type == SCREEN_LVDS)
{
route->lvds_en = 1;
route->lvds_mode = LVDS;
route->lvds_ch_nr = pdata->lvds_ch_nr;
}
else if(screen->type == SCREEN_MIPI)
{
route->lvds_en = 0;
}
return 0;
}
static int rk616_lcd0_input_lcd1_unused_cfg(struct mfd_rk616 *rk616,struct rk_screen *screen,
bool enable)
{
struct rk616_platform_data *pdata = rk616->pdata;
struct rk616_route *route = &rk616->route;
if(enable) //hdmi plug in
{
route->vif0_bypass = 0;
route->vif0_en = 1;
route->vif0_clk_sel = VIF0_CLKIN_SEL(VIF_CLKIN_SEL_PLL0);
route->sclin_sel = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
route->scl_en = 1;
route->sclk_sel = SCLK_SEL(SCLK_SEL_PLL1);
route->dither_sel = DITHER_IN_SEL(DITHER_SEL_SCL); //dither from sclaer
route->hdmi_sel = HDMI_IN_SEL(HDMI_IN_SEL_VIF0);//from vif0
route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF0);
}
else
{
route->vif0_bypass = VIF0_CLK_BYPASS;
route->vif0_en = 0;
route->sclin_sel = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
route->scl_en = 0;
route->dither_sel = DITHER_IN_SEL(DITHER_SEL_VIF0); //dither from sclaer
route->hdmi_sel = HDMI_IN_SEL(HDMI_IN_SEL_VIF0);//from vif0
}
route->pll1_clk_sel = PLL1_CLK_SEL(LCD0_DCLK);
//route->pll0_clk_sel = PLL0_CLK_SEL(LCD0_DCLK);
#if defined(CONFIG_RK616_USE_MCLK_12M)
route->pll0_clk_sel = PLL0_CLK_SEL(MCLK_12M);
#else
route->pll0_clk_sel = PLL0_CLK_SEL(LCD0_DCLK);
#endif
route->vif1_bypass = VIF1_CLK_BYPASS;
route->vif1_en = 0;
route->lcd1_input = 0;
if(screen->type == SCREEN_RGB)
{
route->lvds_en = 1;
route->lvds_mode = RGB; //rgb output
}
else if(screen->type == SCREEN_LVDS)
{
route->lvds_en = 1;
route->lvds_mode = LVDS;
route->lvds_ch_nr = pdata->lvds_ch_nr;
}
else if(screen->type == SCREEN_MIPI)
{
route->lvds_en = 0;
}
return 0;
}
static int rk616_lcd0_input_lcd1_output_cfg(struct mfd_rk616 *rk616,struct rk_screen *screen,
bool enable)
{
struct rk616_route *route = &rk616->route;
if(enable)
{
route->vif0_bypass = 0;
route->vif0_en = 1;
route->vif0_clk_sel = VIF0_CLKIN_SEL(VIF_CLKIN_SEL_PLL0);
route->sclin_sel = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
route->scl_en = 1;
route->sclk_sel = SCLK_SEL(SCLK_SEL_PLL1);
route->dither_sel = DITHER_IN_SEL(DITHER_SEL_SCL); //dither from sclaer
route->hdmi_sel = HDMI_IN_SEL(HDMI_IN_SEL_VIF0);//from vif0
route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF0);
}
else
{
route->vif0_bypass = VIF0_CLK_BYPASS;
route->vif0_en = 0;
route->sclin_sel = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
route->scl_en = 0;
route->dither_sel = DITHER_IN_SEL(DITHER_SEL_VIF0); //dither from sclaer
route->hdmi_sel = HDMI_IN_SEL(HDMI_IN_SEL_VIF0);//from vif0
route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF1);
}
//route->pll0_clk_sel = PLL0_CLK_SEL(LCD0_DCLK);
route->pll1_clk_sel = PLL1_CLK_SEL(LCD0_DCLK);
#if defined(CONFIG_RK616_USE_MCLK_12M)
route->pll0_clk_sel = PLL0_CLK_SEL(MCLK_12M);
#else
route->pll0_clk_sel = PLL0_CLK_SEL(LCD0_DCLK);
#endif
route->vif1_bypass = VIF1_CLK_BYPASS;
route->vif1_en = 0;
route->lcd1_input = 0; //lcd1 as out put
route->lvds_en = 0;
//route->scl_en = 0;
//route->dither_sel = DITHER_IN_SEL(DITHER_SEL_VIF0);
return 0;
}
static int rk616_lcd0_unused_lcd1_input_cfg(struct mfd_rk616 *rk616,struct rk_screen *screen,
bool enable)
{
struct rk616_platform_data *pdata = rk616->pdata;
struct rk616_route *route = &rk616->route;
route->pll0_clk_sel = PLL0_CLK_SEL(LCD1_DCLK);
// route->pll1_clk_sel = PLL1_CLK_SEL(LCD1_DCLK);
#if defined(CONFIG_RK616_USE_MCLK_12M)
route->pll1_clk_sel = PLL1_CLK_SEL(MCLK_12M);
#else
route->pll1_clk_sel = PLL1_CLK_SEL(LCD1_DCLK);
#endif
route->vif0_bypass = VIF0_CLK_BYPASS;
route->vif0_en = 0;
if(enable)
{
route->vif1_bypass = 0;
route->vif1_en = 1;
route->scl_bypass = 0;
}
else
{
route->vif1_bypass = VIF1_CLK_BYPASS;
route->vif1_en = 0;
route->scl_bypass = 1; //1:1 scaler
}
route->vif1_clk_sel = VIF1_CLKIN_SEL(VIF_CLKIN_SEL_PLL1);
route->sclin_sel = SCL_IN_SEL(SCL_SEL_VIF1); //from vif1
route->scl_en = 1;
route->sclk_sel = SCLK_SEL(SCLK_SEL_PLL0);
route->dither_sel = DITHER_IN_SEL(DITHER_SEL_SCL); //dither from sclaer
route->hdmi_sel = HDMI_IN_SEL(HDMI_IN_SEL_VIF1); //from vif1
route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF1);
route->lcd1_input = 1;
if(screen->type == SCREEN_RGB)
{
route->lvds_en = 1;
route->lvds_mode = RGB; //rgb output
}
else if(screen->type == SCREEN_LVDS)
{
route->lvds_en = 1;
route->lvds_mode = LVDS;
route->lvds_ch_nr = pdata->lvds_ch_nr;
}
else if(screen->type == SCREEN_MIPI)
{
route->lvds_en = 0;
}
return 0;
}
int rk616_set_router(struct mfd_rk616 *rk616,struct rk_screen *screen,bool enable)
{
struct rk616_platform_data *pdata = rk616->pdata;
int ret;
if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == INPUT))
{
ret = rk616_dual_input_cfg(rk616,screen,enable);
rk616_dbg(rk616->dev,"rk616 use dual input for dual display!\n");
}
else if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == UNUSED))
{
ret = rk616_lcd0_input_lcd1_unused_cfg(rk616,screen,enable);
rk616_dbg(rk616->dev,
"rk616 use lcd0 as input and lvds/rgb "
"port as output for dual display\n");
}
else if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == OUTPUT))
{
ret = rk616_lcd0_input_lcd1_output_cfg(rk616,screen,enable);
rk616_dbg(rk616->dev,
"rk616 use lcd0 as input and lcd1 as "
"output for dual display\n");
}
else if((pdata->lcd0_func == UNUSED) && (pdata->lcd1_func == INPUT))
{
ret = rk616_lcd0_unused_lcd1_input_cfg(rk616,screen,enable);
rk616_dbg(rk616->dev,
"rk616 use lcd1 as input and lvds/rgb as "
"output for dual display\n");
}
else
{
dev_err(rk616->dev,
"invalid configration,please check your"
"rk616_platform_data setting in your board file!\n");
return -EINVAL;
}
return ret ;
}
static int rk616_router_cfg(struct mfd_rk616 *rk616)
{
u32 val;
int ret;
struct rk616_route *route = &rk616->route;
val = (route->pll0_clk_sel) | (route->pll1_clk_sel) |
PLL1_CLK_SEL_MASK | PLL0_CLK_SEL_MASK; //pll1 clk from lcdc1_dclk,pll0 clk from lcdc0_dclk,mux_lcdx = lcdx_clk
ret = rk616->write_dev(rk616,CRU_CLKSEL0_CON,&val);
val = (route->sclk_sel) | SCLK_SEL_MASK;
ret = rk616->write_dev(rk616,CRU_CLKSEL1_CON,&val);
val = (SCL_IN_SEL_MASK) | (DITHER_IN_SEL_MASK) | (HDMI_IN_SEL_MASK) |
(VIF1_CLKIN_SEL_MASK) | (VIF0_CLKIN_SEL_MASK) | (VIF1_CLK_BYPASS << 16) |
(VIF0_CLK_BYPASS << 16) |(route->sclin_sel) | (route->dither_sel) |
(route->hdmi_sel) | (route->vif1_bypass) | (route->vif0_bypass) |
(route->vif1_clk_sel)| (route->vif0_clk_sel);
ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
val = route->hdmi_clk_sel;
ret = rk616->write_dev_bits(rk616,CRU_CFGMISC_CON,HDMI_CLK_SEL_MASK,&val);
return ret;
}
static int rk616_dither_cfg(struct mfd_rk616 *rk616,struct rk_screen *screen,bool enable)
{
u32 val = 0;
int ret = 0;
if(screen->type != SCREEN_RGB) //if RGB screen , not invert D_CLK
val = FRC_DCLK_INV | (FRC_DCLK_INV << 16);
if((screen->face != OUT_P888) && enable) //enable frc dither if the screen is not 24bit
val |= FRC_DITHER_EN | (FRC_DITHER_EN << 16);
//val |= (FRC_DITHER_EN << 16);
else
val |= (FRC_DITHER_EN << 16);
ret = rk616->write_dev(rk616,FRC_REG,&val);
return 0;
}
int rk616_display_router_cfg(struct mfd_rk616 *rk616,struct rk_screen *screen,bool enable)
{
int ret;
struct rk_screen *hdmi_screen = screen->ext_screen;
ret = rk616_set_router(rk616,screen,enable);
if(ret < 0)
return ret;
ret = rk616_router_cfg(rk616);
/*
If wake up, does not execute the rk616_vif_cfg can save 50ms time
*/
if(rk616->resume != 1){
ret = rk616_vif_cfg(rk616,hdmi_screen,0);
ret = rk616_vif_cfg(rk616,hdmi_screen,1);
}
ret = rk616_scaler_cfg(rk616,screen);
ret = rk616_dither_cfg(rk616,screen,enable);
return 0;
}
int rk616_set_vif(struct mfd_rk616 *rk616,struct rk_screen *screen,bool connect)
{
struct rk616_platform_data *pdata;
if(!rk616)
{
printk(KERN_ERR "%s:mfd rk616 is null!\n",__func__);
return -1;
}
else
{
pdata = rk616->pdata;
}
if(!connect)
{
rk616_vif_disable(rk616,0);
rk616_vif_disable(rk616,1);
rk616_mclk_set_rate(rk616->mclk, 11289600);
return 0;
}
#if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
return 0;
#else
if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == INPUT))
{
rk616_dual_input_cfg(rk616,screen,connect);
rk616_dbg(rk616->dev,"rk616 use dual input for dual display!\n");
}
else if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == UNUSED))
{
rk616_lcd0_input_lcd1_unused_cfg(rk616,screen,connect);
rk616_dbg(rk616->dev,"rk616 use lcd0 input for hdmi display!\n");
}
rk616_router_cfg(rk616);
rk616_vif_cfg(rk616,screen,0);
rk616_vif_cfg(rk616,screen,1);
rk616_scaler_disable(rk616);
#endif
return 0;
}

View File

@ -1,153 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __RK610_CONTROL_H_
#define __RK610_CONTROL_H_
#define INVALID_GPIO -1
//#define RK610_DEBUG
#ifdef RK610_DEBUG
#define RK610_DBG(dev, format, arg...) \
do{\
dev_printk(KERN_INFO , dev , format , ## arg);\
}while(0)
#else
#define RK610_DBG(dev, format, arg...)
#endif
#define RK610_ERR(dev, format, arg...) \
do{\
dev_printk(KERN_ERR , dev , format , ## arg);\
}while(0)
#define RK610_CONTROL_REG_C_PLL_CON0 0x00
#define RK610_CONTROL_REG_C_PLL_CON1 0x01
#define RK610_CONTROL_REG_C_PLL_CON2 0x02
#define RK610_CONTROL_REG_C_PLL_CON3 0x03
#define RK610_CONTROL_REG_C_PLL_CON4 0x04
#define RK610_CONTROL_REG_C_PLL_CON5 0x05
#define C_PLL_DISABLE_FRAC 1 << 0
#define C_PLL_BYPSS_ENABLE 1 << 1
#define C_PLL_POWER_ON 1 << 2
#define C_PLL_LOCLED 1 << 7
#define RK610_CONTROL_REG_TVE_CON 0x29
#define TVE_CONTROL_VDAC_R_BYPASS_ENABLE 1 << 7
#define TVE_CONTROL_VDAC_R_BYPASS_DISABLE 0 << 7
#define TVE_CONTROL_CVBS_3_CHANNEL_ENALBE 1 << 6
#define TVE_CONTROL_CVBS_3_CHANNEL_DISALBE 0 << 5
enum {
INPUT_DATA_FORMAT_RGB888 = 0,
INPUT_DATA_FORMAT_RGB666,
INPUT_DATA_FORMAT_RGB565,
INPUT_DATA_FORMAT_YUV
};
#define RGB2CCIR_INPUT_DATA_FORMAT(n) n << 4
#define RGB2CCIR_RGB_SWAP_ENABLE 1 << 3
#define RGB2CCIR_RGB_SWAP_DISABLE 0 << 3
#define RGB2CCIR_INPUT_INTERLACE 1 << 2
#define RGB2CCIR_INPUT_PROGRESSIVE 0 << 2
#define RGB2CCIR_CVBS_PAL 0 << 1
#define RGB2CCIR_CVBS_NTSC 1 << 1
#define RGB2CCIR_DISABLE 0
#define RGB2CCIR_ENABLE 1
#define RK610_CONTROL_REG_CCIR_RESET 0x2a
#define RK610_CONTROL_REG_CLOCK_CON0 0x2b
#define RK610_CONTROL_REG_CLOCK_CON1 0x2c
#define CLOCK_CON1_I2S_CLK_CODEC_PLL 1 << 5
#define CLOCK_CON1_I2S_DVIDER_MASK 0x1F
#define RK610_CONTROL_REG_CODEC_CON 0x2d
#define CODEC_CON_BIT_HDMI_BLCK_INTERANL 1<<4
#define CODEC_CON_BIT_DAC_LRCL_OUTPUT_DISABLE 1<<3
#define CODEC_CON_BIT_ADC_LRCK_OUTPUT_DISABLE 1<<2
#define CODEC_CON_BIT_INTERAL_CODEC_DISABLE 1<<0
#define RK610_CONTROL_REG_I2C_CON 0x2e
/********************************************************************
** ½á¹¹¨Òå *
********************************************************************/
/* RK610µÄ¼Ä´æÆ÷½á¹¹ */
/* CODEC PLL REG */
#define C_PLL_CON0 0x00
#define C_PLL_CON1 0x01
#define C_PLL_CON2 0x02
#define C_PLL_CON3 0x03
#define C_PLL_CON4 0x04
#define C_PLL_CON5 0x05
/* SCALER PLL REG */
#define S_PLL_CON0 0x06
#define S_PLL_CON1 0x07
#define S_PLL_CON2 0x08
/* LVDS REG */
#define LVDS_CON0 0x09
#define LVDS_CON1 0x0a
/* LCD1 REG */
#define LCD1_CON 0x0b
/* SCALER REG */
#define SCL_CON0 0x0c
#define SCL_CON1 0x0d
#define SCL_CON2 0x0e
#define SCL_CON3 0x0f
#define SCL_CON4 0x10
#define SCL_CON5 0x11
#define SCL_CON6 0x12
#define SCL_CON7 0x13
#define SCL_CON8 0x14
#define SCL_CON9 0x15
#define SCL_CON10 0x16
#define SCL_CON11 0x17
#define SCL_CON12 0x18
#define SCL_CON13 0x19
#define SCL_CON14 0x1a
#define SCL_CON15 0x1b
#define SCL_CON16 0x1c
#define SCL_CON17 0x1d
#define SCL_CON18 0x1e
#define SCL_CON19 0x1f
#define SCL_CON20 0x20
#define SCL_CON21 0x21
#define SCL_CON22 0x22
#define SCL_CON23 0x23
#define SCL_CON24 0x24
#define SCL_CON25 0x25
#define SCL_CON26 0x26
#define SCL_CON27 0x27
#define SCL_CON28 0x28
/* TVE REG */
#define TVE_CON 0x29
/* CCIR REG */
#define CCIR_RESET 0X2a
/* CLOCK REG */
#define CLOCK_CON0 0X2b
#define CLOCK_CON1 0X2c
/* CODEC REG */
#define CODEC_CON 0x2e
#define I2C_CON 0x2f
struct rk610_core_info{
struct i2c_client *client;
struct device *dev;
struct dentry *debugfs_dir;
void *lcd_pdata;
struct clk *i2s_clk;
int reset_gpio;
};
extern int rk610_control_send_byte(const char reg, const char data);
#endif /*end of __RK610_CONTROL_H_*/

View File

@ -1,297 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _RK616_H_
#define _RK616_H_
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/rk_fb.h>
#include <linux/clk.h>
#include <linux/delay.h>
#if defined(CONFIG_RK616_DEBUG)
#define rk616_dbg(dev, format, arg...) \
dev_info(dev , format , ## arg)
#else
#define rk616_dbg(dev, format, arg...) do{}while(0)
#endif
#define VIF0_REG0 0x0000
#define VIF0_DDR_CLK_EN (1<<3)
#define VIF0_DDR_PHASEN_EN (1<<2) //negative edge first en
#define VIF0_DDR_MODE_EN (1<<1)
#define VIF0_EN (1<<0)
#define VIF0_REG1 0x0004
#define VIF0_REG2 0x0008
#define VIF0_REG3 0x000C
#define VIF0_REG4 0x0010
#define VIF0_REG5 0x0014
#define VIF1_REG0 0x0018
#define VIF1_REG1 0x001C
#define VIF1_REG2 0x0020
#define VIF1_REG3 0x0024
#define VIF1_REG4 0x0028
#define VIF1_REG5 0x002C
#define SCL_REG0 0x0030
#define SCL_EN (1<<0)
#define SCL_REG1 0x0034
#define SCL_REG2 0x0038
#define SCL_REG3 0x003C
#define SCL_REG4 0x0040
#define SCL_REG5 0x0044
#define SCL_REG6 0x0048
#define SCL_REG7 0x004C
#define SCL_REG8 0x0050
#define FRC_REG 0x0054
#define FRC_DEN_INV (1<<6)
#define FRC_SYNC_INV (1<<5)
#define FRC_DCLK_INV (1<<4)
#define FRC_OUT_ZERO (1<<3)
#define FRC_RGB18_MODE (1<<2)
#define FRC_HIFRC_MODE (1<<1)
#define FRC_DITHER_EN (1<<0)
#define CRU_CLKSEL0_CON 0x0058
#define PLL1_CLK_SEL_MASK (0x3<<24)
#define PLL0_CLK_SEL_MASK (0x3<<22)
#define LCD1_CLK_DIV_MASK (0x7<<19)
#define LCD0_CLK_DIV_MASK (0x7<<16)
#define PLL1_CLK_SEL(x) (((x)&3)<<8)
#define PLL0_CLK_SEL(x) (((x)&3)<<6)
#define LCD0_DCLK 0
#define LCD1_DCLK 1
#define MCLK_12M 2
#define LCD1_CLK_DIV(x) (((x)&7)<<3)
#define LCD0_CLK_DIV(x) (((x)&7)<<0)
#define CRU_CLKSEL1_CON 0x005C
#define SCLK_SEL_MASK (1<<19)
#define CODEC_MCLK_SEL_MASK (3<<16)
#define LCDC_CLK_GATE (1<<12)
#define LCDC1_CLK_GATE (1<<11)
#define MIPI_CLK_GATE (1<<10)
#define LVDS_CLK_GATE (1<<9)
#define HDMI_CLK_GATE (1<<8)
#define SCL_CLK_DIV(x) (((x)&7)<<5)
#define SCL_CLK_GATE (1<<4)
#define SCLK_SEL(x) (((x)&1)<<3)
#define SCLK_SEL_PLL0 0
#define SCLK_SEL_PLL1 1
#define CODEC_CLK_GATE (1<<2)
#define CODEC_MCLK_SEL(x) (((x)&3)<<0)
#define CODEC_MCLK_SEL_PLL0 0
#define CODEC_MCLK_SEL_PLL1 1
#define CODEC_MCLK_SEL_12M 2
#define CRU_CODEC_DIV 0x0060
#define CRU_CLKSEL2_CON 0x0064
#define SCL_IN_SEL_MASK (1<<31)
#define DITHER_IN_SEL_MASK (1<<30)
#define HDMI_IN_SEL_MASK (3<<28)
#define VIF1_CLK_DIV_MASK (7<<25)
#define VIF0_CLK_DIV_MASK (7<<19)
#define VIF1_CLKIN_SEL_MASK (1<<22)
#define VIF0_CLKIN_SEL_MASK (1<<16)
#define SCL_IN_SEL(x) (((x)&1)<<15)
#define SCL_SEL_VIF0 0
#define SCL_SEL_VIF1 1
#define DITHER_IN_SEL(x) (((x)&1)<<14)
#define DITHER_SEL_VIF0 0
#define DITHER_SEL_SCL 1
#define HDMI_IN_SEL(x) (((x)&3)<<12) //hdmi data in select
#define HDMI_IN_SEL_VIF1 0
#define HDMI_IN_SEL_SCL 1
#define HDMI_IN_SEL_VIF0 2
#define VIF1_CLK_DIV(x) (((x)&7)<<9)
#define VIF1_CLK_GATE (1<<8)
#define VIF1_CLK_BYPASS (1<<7)
#define VIF1_CLKIN_SEL(x) (((x)&1)<<6)
#define VIF_CLKIN_SEL_PLL0 0
#define VIF_CLKIN_SEL_PLL1 1
#define VIF0_CLK_DIV(x) (((x)&7)<<3)
#define VIF0_CLK_GATE (1<<2)
#define VIF0_CLK_BYPASS (1<<1)
#define VIF0_CLKIN_SEL(x) (((x)&1)<<0)
#define CRU_PLL0_CON0 0x0068
#define PLL0_POSTDIV1_MASK (7<<28)
#define PLL0_FBDIV_MASK (0xfff << 16)
#define PLL0_BYPASS (1<<15)
#define PLL0_POSTDIV1(x) (((x)&7)<<12)
#define PLL0_FBDIV(x) (((x)&0xfff)<<0)
#define CRU_PLL0_CON1 0x006C
#define PLL0_DIV_MODE_MASK (1<<25)
#define PLL0_POSTDIV2_MASK (7<<22)
#define PLL0_REFDIV_MASK (0x3f<<16)
#define PLL0_LOCK (1<<15)
#define PLL0_PWR_DN (1<<10)
#define PLL0_DIV_MODE(x) (((x)&1)<<9)
#define PLL0_POSTDIV2(x) (((x)&7)<<6)
#define PLL0_REFDIV(x) (((x)&0x3f)<<0)
#define CRU_PLL0_CON2 0x0070
#define PLL0_FOUT4_PWR_DN (1<<27)
#define PLL0_FOUTVCO_PWR_DN (1<<26)
#define PLL0_POSTDIV_PWR_DN (1<<25)
#define PLL0_DAC_PWR_DN (1<<24)
#define PLL0_FRAC(x) (((x)&0xffffff)<<0)
#define CRU_PLL1_CON0 0x0074
#define PLL1_POSTDIV1_MASK (7<<28)
#define PLL1_FBDIV_MASK (0xfff << 16)
#define PLL1_BYPASS (1<<15)
#define PLL1_POSTDIV1(x) (((x)&7)<<12)
#define PLL1_FBDIV(x) (((x)&0xfff)<<0)
#define CRU_PLL1_CON1 0x0078
#define PLL1_POSTDIV2_MASK (7<<22)
#define PLL1_REFDIV_MASK (0x3f<<16)
#define PLL1_LOCK (1<<15)
#define PLL1_PWR_DN (1<<10)
#define PLL1_DIV_MODE (1<<9)
#define PLL1_POSTDIV2(x) (((x)&7)<<6)
#define PLL1_REFDIV(x) (((x)&0x3f)<<0)
#define CRU_PLL1_CON2 0x007C
#define PLL1_FOUT4_PWR_DN (1<<27)
#define PLL1_FOUTVCO_PWR_DN (1<<26)
#define PLL1_POSTDIV_PWR_DN (1<<25)
#define PLL1_DAC_PWR_DN (1<<24)
#define PLL1_FRAC(x) (((x)&0xffffff)<<0)
#define CRU_I2C_CON0 0x0080
#define CRU_LVDS_CON0 0x0084
#define LVDS_HBP_ODD_MASK (0x1<<30)
#define LVDS_OUT_FORMAT_MASK (3<<16)
#define LVDS_HBP_ODD(x) (((x)&1)<<14)
#define LVDS_DCLK_INV (1<<13)
#define LVDS_CH1_LOAD (1<<12)
#define LVDS_CH0_LOAD (1<<11)
#define LVDS_CH1TTL_EN (1<<10)
#define LVDS_CH0TTL_EN (1<<9)
#define LVDS_CH1_PWR_EN (1<<8)
#define LVDS_CH0_PWR_EN (1<<7)
#define LVDS_CBG_PWR_EN (1<<6)
#define LVDS_PLL_PWR_DN (1<<5)
#define LVDS_START_CH_SEL (1<<4)
#define LVDS_CH_SEL (1<<3)
#define LVDS_MSB_SEL (1<<2)
#define LVDS_OUT_FORMAT(x) (((x)&3)<<0)
#define CRU_IO_CON0 0x0088
#define VIF1_SYNC_EN (1<<15)
#define VIF0_SYNC_EN (1<<14)
#define I2S1_OUT_DISABLE (1<<13)
#define I2S0_OUT_DISABLE (1<<12)
#define LVDS_OUT_EN (1<<11)
#define LCD1_INPUT_EN (1<<10)
#define LVDS_RGBIO_PD_DISABLE (1<<9)
#define LCD1_IO_PD_DISABLE (1<<8)
#define LCD0_IO_PD_DISABLE (1<<7)
#define HDMI_IO_PU_DISABLE (1<<6)
#define SPDIF_IO_PD_DISABLE (1<<5)
#define I2S1_PD_DISABLE (1<<4)
#define I2S0_PD_DISABLE (1<<3)
#define I2C_PU_DISABLE (1<<2)
#define INT_IO_PU (1<<1)
#define CLKIN_PU (1<<0)
#define CRU_IO_CON1 0x008C
#define LVDS_RGBIO_SI_EN (1<<9) //shmitt input enable
#define LCD1_SI_EN (1<<8)
#define LCD0_SI_EN (1<<7)
#define HDMI_SI_EN (1<<6)
#define SPDIF_SI_EN (1<<5)
#define I2S1_SI_EN (1<<4)
#define I2S0_SI_EN (1<<3)
#define I2C_SI_EN (1<<2)
#define INT_SI_EN (1<<1)
#define CLKIN_SI_EN (1<<0)
#define CRU_PCM2IS2_CON0 0x0090
#define CRU_PCM2IS2_CON1 0x0094
#define CRU_PCM2IS2_CON2 0x0098
#define CRU_CFGMISC_CON 0x009C
#define HDMI_CLK_SEL_MASK (3<<12)
#define HDMI_CLK_SEL(x) (((x)&3)<<12) //hdmi data in select
#define HDMI_CLK_SEL_VIF1 0
#define HDMI_CLK_SEL_SCL 1
#define HDMI_CLK_SEL_VIF0 2
enum lcd_port_func{ // the function of lcd ports(lcd0,lcd1),the lcd0 only can be used as input or unused
UNUSED, // the lcd1 can be used as input,output or unused
INPUT,
OUTPUT,
};
enum lvds_mode {
RGB,
LVDS,
};
struct rk616_platform_data {
int (*power_init)(void);
int (*power_deinit)(void);
int scl_rate;
enum lcd_port_func lcd0_func;
enum lcd_port_func lcd1_func;
int lvds_ch_nr; //the number of used lvds channel
int hdmi_irq;
};
struct rk616_route {
u16 vif0_bypass;
u8 vif0_en;
u16 vif0_clk_sel;
u16 vif1_bypass;
u8 vif1_en;
u16 vif1_clk_sel;
u16 sclin_sel;
u8 scl_en;
u8 scl_bypass;
u16 dither_sel;
u16 hdmi_sel;
u16 hdmi_clk_sel;
u16 pll0_clk_sel;
u16 pll1_clk_sel;
u16 sclk_sel;
u8 lcd1_input;
u8 lvds_en;
enum lvds_mode lvds_mode; //RGB or LVDS
int lvds_ch_nr; //the number of used lvds channel
};
struct mfd_rk616 {
struct mutex reg_lock;
struct device *dev;
unsigned int irq_base;
struct rk616_platform_data *pdata;
struct rk616_route route; //display path router
struct i2c_client *client;
struct clk *mclk;
u64 pll0_rate;
u64 pll1_rate;
unsigned int resume;
struct dentry *debugfs_dir;
int (*read_dev)(struct mfd_rk616 *rk616,u16 reg,u32 *pval);
int (*write_dev)(struct mfd_rk616 *rk616,u16 reg,u32 *pval);
int (*write_dev_bits)(struct mfd_rk616 *rk616,u16 reg,u32 mask,u32 *pval);
int (*write_bulk)(struct mfd_rk616 *rk616,u16 reg,int count,u32 *pval);
};
extern int rk616_set_vif(struct mfd_rk616 * rk616,struct rk_screen * screen,bool connect);
extern int rk616_display_router_cfg(struct mfd_rk616 *rk616,struct rk_screen *screen,bool enable);
extern void rk616_mclk_set_rate(struct clk *mclk,unsigned long rate);
#endif