mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
mfd: Drop unused rk610/rk616 driver
Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com> Change-Id: I76c73d0c565b04261a099373c7a9200d6058b8ec
This commit is contained in:
@@ -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 = ®_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", ®,&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");
|
||||
|
||||
@@ -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, ®, 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, ®, 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,®_val);
|
||||
reg_val &= ~mask;
|
||||
*pval &= mask;
|
||||
reg_val |= *pval;
|
||||
*pval = reg_val;
|
||||
memcpy(tx_buf, ®, 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, ®, 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", ®,&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);
|
||||
|
||||
|
||||
@@ -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的缩放模式 0:no_scl 1:scl_up 2:scl_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的缩放模式 0:no_scl 1:scl_up 2:scl_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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user