mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
mfd: display-serdes: improve drivers about these case
1.set lcd low level before set high level 2.set label for lock&err gpio and irq 3.add monitor function for serdes important register Signed-off-by: Luo Wei <lw@rock-chips.com> Change-Id: I6e0ee19de04dec87fd356a6f5cb046612bec3451
This commit is contained in:
@@ -106,7 +106,7 @@
|
||||
#define SERDES_DBG_CHIP(x...) no_printk(x)
|
||||
#endif
|
||||
|
||||
#define MFD_SERDES_DISPLAY_VERSION "serdes-mfd-displaly-v11-240815"
|
||||
#define MFD_SERDES_DISPLAY_VERSION "serdes-mfd-displaly-v11-241025"
|
||||
#define MAX_NUM_SERDES_SPLIT 8
|
||||
struct serdes;
|
||||
enum ser_link_mode {
|
||||
@@ -116,6 +116,11 @@ enum ser_link_mode {
|
||||
SER_SPLITTER_MODE,
|
||||
};
|
||||
|
||||
struct check_reg_data {
|
||||
char name[30];
|
||||
struct reg_sequence seq;
|
||||
};
|
||||
|
||||
struct serdes_chip_pinctrl_info {
|
||||
struct pinctrl_pin_desc *pins;
|
||||
unsigned int num_pins;
|
||||
@@ -181,6 +186,10 @@ struct serdes_chip_split_ops {
|
||||
int (*set_i2c_addr)(struct serdes *serdes, int address, int link);
|
||||
};
|
||||
|
||||
struct serdes_check_reg_ops {
|
||||
int (*check_reg)(struct serdes *serdes);
|
||||
};
|
||||
|
||||
struct serdes_chip_pm_ops {
|
||||
/* serdes chip function for suspend and resume */
|
||||
int (*suspend)(struct serdes *serdes);
|
||||
@@ -217,6 +226,7 @@ struct serdes_chip_data {
|
||||
struct serdes_chip_pinctrl_ops *pinctrl_ops;
|
||||
struct serdes_chip_gpio_ops *gpio_ops;
|
||||
struct serdes_chip_split_ops *split_ops;
|
||||
struct serdes_check_reg_ops *check_ops;
|
||||
struct serdes_chip_pm_ops *pm_ops;
|
||||
struct serdes_chip_irq_ops *irq_ops;
|
||||
};
|
||||
@@ -373,6 +383,7 @@ struct serdes {
|
||||
int lock_irq_trig;
|
||||
int err_irq_trig;
|
||||
atomic_t flag_ser_init;
|
||||
atomic_t flag_early_suspend;
|
||||
|
||||
struct workqueue_struct *mfd_wq;
|
||||
struct delayed_work mfd_delay_work;
|
||||
|
||||
@@ -856,6 +856,49 @@ static struct serdes_chip_split_ops max96745_split_ops = {
|
||||
.deselect = max96745_deselect,
|
||||
};
|
||||
|
||||
static const struct check_reg_data max96745_improtant_reg[10] = {
|
||||
{
|
||||
"MAX96745 LINK LOCK",
|
||||
{ 0x0013, (1 << 3) },
|
||||
}, {
|
||||
"MAX96745 LINKA LOCK",
|
||||
{ 0x002A, (1 << 0) },
|
||||
}, {
|
||||
"MAX96745 LINKB LOCK",
|
||||
{ 0x0034, (1 << 0) },
|
||||
}, {
|
||||
"MAX96745 X PCLK DET",
|
||||
{ 0x0102, (1 << 7) },
|
||||
}, {
|
||||
"MAX96745 Y PCLK DET",
|
||||
{ 0x0112, (1 << 7) },
|
||||
},
|
||||
};
|
||||
|
||||
static int max96745_check_reg(struct serdes *serdes)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
unsigned int val = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(max96745_improtant_reg); i++) {
|
||||
if (!max96745_improtant_reg[i].seq.reg)
|
||||
break;
|
||||
|
||||
ret = serdes_reg_read(serdes, max96745_improtant_reg[i].seq.reg, &val);
|
||||
if (!ret && !(val & max96745_improtant_reg[i].seq.def)
|
||||
&& (!atomic_read(&serdes->flag_early_suspend)))
|
||||
dev_info(serdes->dev, "warning %s %s reg[0x%x] = 0x%x\n", __func__,
|
||||
max96745_improtant_reg[i].name,
|
||||
max96745_improtant_reg[i].seq.reg, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct serdes_check_reg_ops max96745_check_reg_ops = {
|
||||
.check_reg = max96745_check_reg,
|
||||
};
|
||||
|
||||
static int max96745_pm_suspend(struct serdes *serdes)
|
||||
{
|
||||
return 0;
|
||||
@@ -897,6 +940,7 @@ struct serdes_chip_data serdes_max96745_data = {
|
||||
.pinctrl_ops = &max96745_pinctrl_ops,
|
||||
.gpio_ops = &max96745_gpio_ops,
|
||||
.split_ops = &max96745_split_ops,
|
||||
.check_ops = &max96745_check_reg_ops,
|
||||
.pm_ops = &max96745_pm_ops,
|
||||
.irq_ops = &max96745_irq_ops,
|
||||
};
|
||||
|
||||
@@ -601,6 +601,40 @@ static struct serdes_chip_split_ops max96752_split_ops = {
|
||||
.set_i2c_addr = max96752_set_i2c_addr,
|
||||
};
|
||||
|
||||
static const struct check_reg_data max96752_improtant_reg[10] = {
|
||||
{
|
||||
"MAX96752 VIDEO LOCK",
|
||||
{ 0x0003, (1 << 0) },
|
||||
}, {
|
||||
"MAX96752 VIDEO LOCK",
|
||||
{ 0x0108, (1 << 6) },
|
||||
},
|
||||
};
|
||||
|
||||
static int max96752_check_reg(struct serdes *serdes)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
unsigned int val = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(max96752_improtant_reg); i++) {
|
||||
if (!max96752_improtant_reg[i].seq.reg)
|
||||
break;
|
||||
|
||||
ret = serdes_reg_read(serdes, max96752_improtant_reg[i].seq.reg, &val);
|
||||
if (!ret && !(val & max96752_improtant_reg[i].seq.def)
|
||||
&& (!atomic_read(&serdes->flag_early_suspend)))
|
||||
dev_info(serdes->dev, "warning %s %s reg[0x%x] = 0x%x\n", __func__,
|
||||
max96752_improtant_reg[i].name,
|
||||
max96752_improtant_reg[i].seq.reg, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct serdes_check_reg_ops max96752_check_reg_ops = {
|
||||
.check_reg = max96752_check_reg,
|
||||
};
|
||||
|
||||
static int max96752_pm_suspend(struct serdes *serdes)
|
||||
{
|
||||
return 0;
|
||||
@@ -642,6 +676,7 @@ struct serdes_chip_data serdes_max96752_data = {
|
||||
.bridge_ops = &max96752_bridge_ops,
|
||||
.pinctrl_ops = &max96752_pinctrl_ops,
|
||||
.split_ops = &max96752_split_ops,
|
||||
.check_ops = &max96752_check_reg_ops,
|
||||
.gpio_ops = &max96752_gpio_ops,
|
||||
.pm_ops = &max96752_pm_ops,
|
||||
.irq_ops = &max96752_irq_ops,
|
||||
|
||||
@@ -772,6 +772,43 @@ static struct serdes_chip_split_ops max96789_split_ops = {
|
||||
.deselect = max96789_deselect,
|
||||
};
|
||||
|
||||
static const struct check_reg_data max96789_improtant_reg[10] = {
|
||||
{
|
||||
"MAX96789 LINK LOCK",
|
||||
{ 0x0013, (1 << 3) },
|
||||
}, {
|
||||
"MAX96789 X PCLK DET",
|
||||
{ 0x0102, (1 << 7) },
|
||||
}, {
|
||||
"MAX96789 Y PCLK DET",
|
||||
{ 0x0112, (1 << 7) },
|
||||
},
|
||||
};
|
||||
|
||||
static int max96789_check_reg(struct serdes *serdes)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
unsigned int val = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(max96789_improtant_reg); i++) {
|
||||
if (!max96789_improtant_reg[i].seq.reg)
|
||||
break;
|
||||
|
||||
ret = serdes_reg_read(serdes, max96789_improtant_reg[i].seq.reg, &val);
|
||||
if (!ret && !(val & max96789_improtant_reg[i].seq.def)
|
||||
&& (!atomic_read(&serdes->flag_early_suspend)))
|
||||
dev_info(serdes->dev, "warning %s %s reg[0x%x] = 0x%x\n", __func__,
|
||||
max96789_improtant_reg[i].name,
|
||||
max96789_improtant_reg[i].seq.reg, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct serdes_check_reg_ops max96789_check_reg_ops = {
|
||||
.check_reg = max96789_check_reg,
|
||||
};
|
||||
|
||||
static int max96789_pm_suspend(struct serdes *serdes)
|
||||
{
|
||||
return 0;
|
||||
@@ -813,6 +850,7 @@ struct serdes_chip_data serdes_max96789_data = {
|
||||
.pinctrl_ops = &max96789_pinctrl_ops,
|
||||
.gpio_ops = &max96789_gpio_ops,
|
||||
.split_ops = &max96789_split_ops,
|
||||
.check_ops = &max96789_check_reg_ops,
|
||||
.pm_ops = &max96789_pm_ops,
|
||||
.irq_ops = &max96789_irq_ops,
|
||||
};
|
||||
|
||||
@@ -238,7 +238,7 @@ static int serdes_bridge_split_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct serdes_bridge_split *serdes_bridge_split;
|
||||
|
||||
if (!serdes->dev)
|
||||
if (!serdes->dev || !serdes->chip_data)
|
||||
return -1;
|
||||
|
||||
serdes_bridge_split = devm_kzalloc(dev, sizeof(*serdes_bridge_split), GFP_KERNEL);
|
||||
|
||||
@@ -243,7 +243,7 @@ static int serdes_bridge_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct serdes_bridge *serdes_bridge;
|
||||
|
||||
if (!serdes->dev)
|
||||
if (!serdes->dev || !serdes->chip_data)
|
||||
return -1;
|
||||
|
||||
serdes_bridge = devm_kzalloc(dev, sizeof(*serdes_bridge), GFP_KERNEL);
|
||||
|
||||
@@ -171,6 +171,9 @@ static int serdes_i2c_check_register(struct serdes *serdes, int *flag)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (serdes->chip_data->check_ops->check_reg)
|
||||
ret = serdes->chip_data->check_ops->check_reg(serdes);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -207,6 +210,7 @@ static int serdes_reg_check_work_setup(struct serdes *serdes)
|
||||
return PTR_ERR(serdes->kworker);
|
||||
mutex_init(&serdes->reg_check_lock);
|
||||
atomic_set(&serdes->flag_ser_init, 1);
|
||||
atomic_set(&serdes->flag_early_suspend, 0);
|
||||
kthread_queue_delayed_work(serdes->kworker, &serdes->reg_check_work,
|
||||
msecs_to_jiffies(20000));
|
||||
|
||||
@@ -463,6 +467,11 @@ static void serdes_i2c_remove(struct i2c_client *client)
|
||||
|
||||
static int serdes_i2c_prepare(struct device *dev)
|
||||
{
|
||||
struct serdes *serdes = dev_get_drvdata(dev);
|
||||
|
||||
atomic_set(&serdes->flag_early_suspend, 1);
|
||||
|
||||
SERDES_DBG_MFD("%s: name=%s\n", __func__, dev_name(serdes->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -473,6 +482,7 @@ static void serdes_i2c_complete(struct device *dev)
|
||||
if (serdes->chip_data->serdes_type == TYPE_SER)
|
||||
serdes_i2c_set_sequence(serdes);
|
||||
|
||||
atomic_set(&serdes->flag_early_suspend, 0);
|
||||
SERDES_DBG_MFD("%s: name=%s\n", __func__, dev_name(serdes->dev));
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,9 @@ int serdes_irq_init(struct serdes *serdes)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!serdes->dev || !serdes->chip_data)
|
||||
return -1;
|
||||
|
||||
mutex_init(&serdes->irq_lock);
|
||||
|
||||
/* lock irq */
|
||||
@@ -53,6 +56,9 @@ int serdes_irq_init(struct serdes *serdes)
|
||||
"failed to get serdes lock GPIO\n");
|
||||
|
||||
if (serdes->lock_gpio) {
|
||||
serdes->lock_gpio->label = devm_kasprintf(serdes->dev, GFP_KERNEL,
|
||||
"lock-%s-%s", dev_name(serdes->dev),
|
||||
serdes->chip_data->name);
|
||||
serdes->lock_irq = gpiod_to_irq(serdes->lock_gpio);
|
||||
if (serdes->lock_irq < 0)
|
||||
return serdes->lock_irq;
|
||||
@@ -64,7 +70,7 @@ int serdes_irq_init(struct serdes *serdes)
|
||||
ret = devm_request_threaded_irq(serdes->dev, serdes->lock_irq, NULL,
|
||||
serdes_bridge_lock_irq_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
dev_name(serdes->dev), serdes);
|
||||
serdes->lock_gpio->label, serdes);
|
||||
if (ret)
|
||||
return dev_err_probe(serdes->dev, ret,
|
||||
"failed to request serdes lock IRQ\n");
|
||||
@@ -77,6 +83,9 @@ int serdes_irq_init(struct serdes *serdes)
|
||||
"failed to get serdes err GPIO\n");
|
||||
|
||||
if (serdes->err_gpio) {
|
||||
serdes->err_gpio->label = devm_kasprintf(serdes->dev, GFP_KERNEL,
|
||||
"err-%s-%s", dev_name(serdes->dev),
|
||||
serdes->chip_data->name);
|
||||
serdes->err_irq = gpiod_to_irq(serdes->err_gpio);
|
||||
if (serdes->err_irq < 0)
|
||||
return serdes->err_irq;
|
||||
@@ -87,7 +96,7 @@ int serdes_irq_init(struct serdes *serdes)
|
||||
ret = devm_request_threaded_irq(serdes->dev, serdes->err_irq, NULL,
|
||||
serdes_bridge_err_irq_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
dev_name(serdes->dev), serdes);
|
||||
serdes->err_gpio->label, serdes);
|
||||
if (ret)
|
||||
return dev_err_probe(serdes->dev, ret, "failed to request err IRQ\n");
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ static int serdes_panel_split_prepare(struct drm_panel *panel)
|
||||
if (serdes->chip_data->panel_ops && serdes->chip_data->panel_ops->prepare)
|
||||
ret = serdes->chip_data->panel_ops->prepare(serdes);
|
||||
|
||||
serdes_set_pinctrl_sleep(serdes);
|
||||
serdes_set_pinctrl_default(serdes);
|
||||
|
||||
SERDES_DBG_MFD("%s: %s\n", __func__, serdes->chip_data->name);
|
||||
|
||||
@@ -29,6 +29,7 @@ static int serdes_panel_prepare(struct drm_panel *panel)
|
||||
if (serdes->chip_data->panel_ops && serdes->chip_data->panel_ops->prepare)
|
||||
ret = serdes->chip_data->panel_ops->prepare(serdes);
|
||||
|
||||
serdes_set_pinctrl_sleep(serdes);
|
||||
serdes_set_pinctrl_default(serdes);
|
||||
|
||||
SERDES_DBG_MFD("%s: %s\n", __func__, serdes->chip_data->name);
|
||||
|
||||
@@ -229,7 +229,7 @@ static int serdes_pinctrl_probe(struct platform_device *pdev)
|
||||
int pin_base = 0;
|
||||
int i, j, ret;
|
||||
|
||||
if (!serdes->dev)
|
||||
if (!serdes->dev || !serdes->chip_data)
|
||||
return -1;
|
||||
|
||||
pinctrl_info = chip_data->pinctrl_info;
|
||||
|
||||
Reference in New Issue
Block a user