MSM8916 ICN6211 MIPI2RGB调试

1. DTSI

1> i2c:

    i2c@78b9000 { /* BLSP1 QUP5 */
            icn6211@2c {
                        compatible = "qcom,icn6211";
                        reg = <0x2C>;
                        pinctrl-names = "default","sleep";
                        pinctrl-0 = <&icn_default>;
                        pinctrl-1 = <&icn_sleep>;
                        icn,gpio_rstn = <&msm_gpio 21 0x0>;
                        icn,gpio_3V3_en = <&msm_gpio 51 0x0>;
                        icn,gpio_dc_5v_en = <&msm_gpio 50 0x0>;
                        vdd-supply = <&pm8916_l6>;    
                };
     };

2> pin-ctrl:

		icn6211_reset_pin {
			qcom,pins = <&gp 21>;
			qcom,pin-func = <0>;
			qcom,num-grp-pins = <1>;
			label = "icn6211_reset_pin";
			icn_default: icn_default {
				drive-strength = <6>;
				bias-pull-up;
			};
			icn_sleep: icn_sleep {
				drive-strength = <2>;
				bias-pull-down;
			};
		};

2. 驱动:


#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/workqueue.h>
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>

#include "mdss_i2c_interface.h"
#include "mdss_dsi.h"

struct mdss_i2c_interface {
	unsigned short flags;
	struct i2c_client *mdss_mipi_i2c_client;
	unsigned int slave_addr ;
	struct mutex lock;
	struct mutex i2c_lock;
	int gpio_rstn ;//for icn6211
	int gpio_3V3_en;
	int gpio_dc_5v_en;
	struct pinctrl		*pinctrl;
	struct pinctrl_state	*pin_default;
	struct pinctrl_state	*pin_sleep;
	
	struct regulator *vdd;
};

static struct mdss_i2c_interface *my_mipi_i2c ;


/*if I2C_TEST_OK == 1 stand for icn6211's i2c no ack , and the 
resource of my_mipi_i2c has been remove .must be stop here !
or will happen null pointer error !
*/

static int I2C_TEST_OK  = 0 ; //default
	
int HDMI_WriteI2C_Byte(int reg, int val)
{
	int rc = 0;
	rc = i2c_smbus_write_byte_data(my_mipi_i2c->mdss_mipi_i2c_client,reg,val);
	if (rc < 0) {
		printk("eliot :HDMI_WriteI2C_Byte fail \n");
        return rc;
		}
	return rc ;
}
int HDMI_ReadI2C_Byte(int reg)
{
	int val = 0;
	val = i2c_smbus_read_byte_data(my_mipi_i2c->mdss_mipi_i2c_client, reg);
    if (val < 0) {
        dev_err(&my_mipi_i2c->mdss_mipi_i2c_client->dev, "i2c read fail: can't read from %02x: %d\n", 0, val);
        return val;
    } 
	return val ;
}

static int Reset_chip(void)
{

	gpio_direction_output(my_mipi_i2c->gpio_rstn, 0);
	mdelay(50);

	gpio_direction_output(my_mipi_i2c->gpio_rstn, 1);

	return 0;
}

/*This function para Get from FAE*/
int mdss_mipi_i2c_init(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
{
	//printk(KERN_ERR "eliot :mdss_mipi_i2c_init start \n");
	//Reset_chip();
	/*if I2C_TEST_OK == 1 stand for icn6211's i2c no ack , and the 
	resource of my_mipi_i2c has been remove .must be stop here !
	*/
	if(I2C_TEST_OK  == 0)
	{
		printk(KERN_ERR "eliot :i2c test erro or mdss i2c interface donot probe \n");
		return 0;
	}
	// 往ICN6211寄存器写值:
	//******************************************//
		mutex_lock(&my_mipi_i2c->i2c_lock);

		HDMI_WriteI2C_Byte(0x20 , 0x00);// Register address : 0x08;	Value : 0xff
		HDMI_WriteI2C_Byte(0x21 , 0xD0);
		HDMI_WriteI2C_Byte(0x22 , 0x25);
		HDMI_WriteI2C_Byte(0x23 , 0x6E);
		HDMI_WriteI2C_Byte(0x24 , 0x28);
		HDMI_WriteI2C_Byte(0x25 , 0xDC);
		HDMI_WriteI2C_Byte(0x26 , 0x00);
		HDMI_WriteI2C_Byte(0x27 , 0x05);
		HDMI_WriteI2C_Byte(0x28 , 0x05);
		HDMI_WriteI2C_Byte(0x29 , 0x14);
		HDMI_WriteI2C_Byte(0x34 , 0x80);
		HDMI_WriteI2C_Byte(0x36 , 0x6E);
		HDMI_WriteI2C_Byte(0xB5 , 0xA0);
		HDMI_WriteI2C_Byte(0x5C , 0xFF);
		HDMI_WriteI2C_Byte(0x2A , 0x07);
		HDMI_WriteI2C_Byte(0x56 , 0x92);
		HDMI_WriteI2C_Byte(0x6B , 0x52);
		HDMI_WriteI2C_Byte(0x69 , 0x2C);
		HDMI_WriteI2C_Byte(0x10 , 0x40);
		HDMI_WriteI2C_Byte(0x11 , 0x88);
		HDMI_WriteI2C_Byte(0xB6 , 0x20);
		HDMI_WriteI2C_Byte(0x51 , 0x20);
		HDMI_WriteI2C_Byte(0x09 , 0x10);
		
		mutex_unlock(&my_mipi_i2c->i2c_lock);

		//printk(KERN_ERR "eliot :mdss_mipi_i2c_init end \n");
		return 0 ;
	
}

EXPORT_SYMBOL_GPL(mdss_mipi_i2c_init);

static int lt_pinctrl_init(struct mdss_i2c_interface *lt)
{
	struct i2c_client *client = lt->mdss_mipi_i2c_client;

	lt->pinctrl = devm_pinctrl_get(&client->dev);
	if (IS_ERR_OR_NULL(lt->pinctrl)) {
		dev_err(&client->dev, "Failed to get pinctrl\n");
		return PTR_ERR(lt->pinctrl);
	}

	lt->pin_default = pinctrl_lookup_state(lt->pinctrl, "default");
	if (IS_ERR_OR_NULL(lt->pin_default)) {
		dev_err(&client->dev, "Failed to look up default state\n");
		return PTR_ERR(lt->pin_default);
	}

	lt->pin_sleep = pinctrl_lookup_state(lt->pinctrl, "sleep");
	if (IS_ERR_OR_NULL(lt->pin_sleep)) {
		dev_err(&client->dev, "Failed to look up sleep state\n");
		return PTR_ERR(lt->pin_sleep);
	}

	return 0;
}

/*
	1.get reset pin and request gpio ;
	2.get i2c client ,check i2c function and test read i2c slave ;
	3.send icn6211i2c configuration table
*/
#define I2C_VTG_MIN_UV	1800000
#define I2C_VTG_MAX_UV	1800000

static int mipi_i2c_probe(struct i2c_client *client,
        const struct i2c_device_id *id) 
{
  int err;
	struct mdss_dsi_ctrl_pdata *ctrl=NULL;
	int from_mdp=0 ;

	printk(KERN_ERR "eliot :mipi_i2c_probe start.....");
	
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		dev_err(&client->dev,
				"%s: check_functionality failed.", __func__);
		err = -ENODEV;
		goto exit0;
	}

	/* Allocate memory for driver data */
	my_mipi_i2c = kzalloc(sizeof(struct mdss_i2c_interface), GFP_KERNEL);
	if (!my_mipi_i2c) {
		dev_err(&client->dev,
				"%s: memory allocation failed.", __func__);
		err = -ENOMEM;
		goto exit1;
	}
	
	mutex_init(&my_mipi_i2c->lock);
	mutex_init(&my_mipi_i2c->i2c_lock);

	if (client->dev.of_node) {
	my_mipi_i2c->gpio_rstn = of_get_named_gpio_flags(client->dev.of_node,
			"icn,gpio_rstn", 0, NULL);
	my_mipi_i2c->gpio_3V3_en= of_get_named_gpio_flags(client->dev.of_node,
			"icn,gpio_3V3_en", 0, NULL);
	my_mipi_i2c->gpio_dc_5v_en= of_get_named_gpio_flags(client->dev.of_node,
			"icn,gpio_dc_5v_en", 0, NULL);
	//printk("eliot:my_mipi_i2c->gpio_rstn=%d\n",my_mipi_i2c->gpio_rstn);
	}
	else
	{
		printk(KERN_ERR "eliot:client->dev.of_node not exit!\n");
	}

	/***** I2C initialization *****/
	my_mipi_i2c->mdss_mipi_i2c_client = client;
	
	/* set client data */
	i2c_set_clientdata(client, my_mipi_i2c);

		/*donot free power , camera using else*/
	err = gpio_request(my_mipi_i2c->gpio_3V3_en, "gpio_3V3_en");
	err = gpio_request(my_mipi_i2c->gpio_dc_5v_en, "gpio_dc_5v_en");
	gpio_direction_output(my_mipi_i2c->gpio_3V3_en, 1);
	gpio_direction_output(my_mipi_i2c->gpio_dc_5v_en, 1);
	
	/*open l6 1.8 V*/
	
	my_mipi_i2c->vdd = regulator_get(&client->dev, "vdd");
	if (IS_ERR(my_mipi_i2c->vdd)) {
		err = PTR_ERR(my_mipi_i2c->vdd);
		printk(KERN_ERR "eliot:vdd get erro err = %d\n",err);
		goto exit1;
	}else
	{
		regulator_set_voltage(my_mipi_i2c->vdd, I2C_VTG_MIN_UV,
					   I2C_VTG_MAX_UV);
		err = regulator_enable(my_mipi_i2c->vdd);
		if (err) {
			dev_err(&client->dev,
				"Regulator vdd enable failed ret=%d\n", err);
			goto exit2;
		}
	}

	
	/* initialize pinctrl */
	if (!lt_pinctrl_init(my_mipi_i2c)) {
		err = pinctrl_select_state(my_mipi_i2c->pinctrl, my_mipi_i2c->pin_default);
		if (err) {
			dev_err(&client->dev, "Can't select pinctrl state\n");
			goto exit2;
		}
	}
	mutex_lock(&my_mipi_i2c->lock);

	/* Pull up the reset pin */
	/* request  GPIO  */
	err = gpio_request(my_mipi_i2c->gpio_rstn, "icn6211_rsrn");
	if (err < 0) {
		mutex_unlock(&my_mipi_i2c->lock);
		printk(KERN_ERR "Failed to request GPIO:%d, ERRNO:%d",
			  my_mipi_i2c->gpio_rstn, err);
		err = -ENODEV;
		goto exit2;
	}else{
			gpio_direction_output(my_mipi_i2c->gpio_rstn, 0);
			mdelay(50);
			gpio_direction_output(my_mipi_i2c->gpio_rstn, 1);
		}
		//printk(KERN_ERR "eliot :icn6211 addr = 0x%x ....\n",my_mipi_i2c->mdss_mipi_i2c_client->addr);
    err = i2c_smbus_read_byte_data(client, 0x0);
    if ((err < 0)&&(err != 0xc1)) {
			//I2C_TEST_OK = 0 ;
			mutex_unlock(&my_mipi_i2c->lock);
			gpio_direction_output(my_mipi_i2c->gpio_rstn, 0);
			dev_err(&client->dev, "i2c read fail: can't read from %02x: %d\n", client->addr, err);
	        goto exit3;
    } 
	I2C_TEST_OK = 1 ;
  //printk(KERN_ERR "eliot :icn6211 reg 0 val = 0x%x ....\n",err);
	mdss_mipi_i2c_init(ctrl,from_mdp);
	mutex_unlock(&my_mipi_i2c->lock);
	printk(KERN_ERR "eliot :mipi_i2c_probe end ....\n");
	return 0;
exit3:
	gpio_free(my_mipi_i2c->gpio_rstn);

exit2:
	regulator_disable(my_mipi_i2c->vdd);
exit1:
	mutex_destroy(&my_mipi_i2c->lock);
	mutex_destroy(&my_mipi_i2c->i2c_lock);
	kfree(my_mipi_i2c);
exit0:
	return err;

}

static const struct of_device_id mipi_i2c_of_match[] = {
    { .compatible = "qcom,icn6211",},
    {},
};

static const struct i2c_device_id mipi_i2c_id[] = {
    {"qcom,icn6211", 0},
    {},
};
static int mipi_i2c_resume(struct device *tdev) {
	Reset_chip();
    return 0;
}

static int mipi_i2c_remove(struct i2c_client *client) {
	
    return 0;
}

static int mipi_i2c_suspend(struct device *tdev) {
	gpio_direction_output(my_mipi_i2c->gpio_rstn, 0);
    return 0;
}

static const struct dev_pm_ops mipi_i2c_pm_ops =
{ 
    .suspend = mipi_i2c_suspend,
    .resume = mipi_i2c_resume, 
};


static struct i2c_driver mipi_i2c_driver = {
    .driver = {
        .name = "qcom,icn6211",
        .owner    = THIS_MODULE,
        .of_match_table = mipi_i2c_of_match,
        .pm = &mipi_i2c_pm_ops,
    },
    .probe    = mipi_i2c_probe,
    .remove   = mipi_i2c_remove,
    .id_table = mipi_i2c_id,
};

module_i2c_driver(mipi_i2c_driver);

MODULE_LICENSE("GPL");

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

村里小码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值