WinCE下的TVP5146调试助手

     这两天在调试TVP5146的驱动程序,之前一直都是LF在负责,现在刚刚接手,很多细节都不清楚。不管三七二十一,先做了一个用于读写TVP5146所有内部寄存器的小工具,通过它可以实时修改其中的任意一个寄存器,而不必编译驱动或内核。

     实现了这个小工具后,首先切换了一下输入的通道,工作得很好,又从AVIN模式切换到DVD模式,也能看见画面了,虽然有些闪烁,而这就是接下来需要解决的细节问题。

     从网上找到了一份Linux下的参考代码,原厂发布出来的,看上去很靠谱,收藏在这,以备不时之需。

/*
 *
 *
 * Copyright (C) 2006 Texas Instruments Inc
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
/* tvp5146.c */

//phoenix
//modified 2008.01.04 PM 15:00 
//linger
//last modified 2007.12.27 PM 17:00
//last modified 2007.11.30 PM 18:00
//last modified 2007.11.29 PM 18:00

#include <linux/config.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/videodev.h>
#include <media/tvp5146.h>            //phoenix 2008/05/14    dvs6446 updates to 

dvevm_1_20
#include <asm/arch/gio.h>         //linger 2007.11.8

#define debug_print(x...)    //printk(x)

static struct i2c_client tvp5146_i2c_client;
static struct i2c_driver tvp5146_i2c_driver;
static int tvp5146_i2c_registration = 0;
struct device *tvp5146_i2c_dev;

static int i2c_read_reg(struct i2c_client *client, u8 reg, u8 * val);
static int i2c_write_reg(struct i2c_client *client, u8 reg, u8 val);

static int configtvp5146(void *arg);
static int clrtvp5146lostlock(void);
static int enabletvp5146agc(int arg);
static int getctrl(void *arg);
static int gettvp5146status(void *arg);
static int powerdowntvp5146(int powerdownenable);
static int queryctrl(void *arg);
static int resettvp5146(void);
static int setctrl(void *arg);
static int settvp5146amuxmode(int mode);
static int settvp5146brightness(int arg);
static int settvp5146contrast(int arg);
static int settvp5146hue(int arg);
static int settvp5146saturation(int arg);
static int settvp5146std(int arg);
//static int setup656sync(int enable);
static int setup656sync(tvp5146_params * tvp5146params);

/*
 * ======== tvp5146_init  ========
 */
/* This function is used initialize TVP5146 i2c client */
static int tvp5146_init(void)
{
    int err;
    struct i2c_driver *driver = &tvp5146_i2c_driver;
    err = i2c_add_driver(driver);
    if (err) {
        printk(KERN_ERR "Failed to register TVP5146 I2C client.\n");
    } else {
        tvp5146_i2c_registration = TVP5146_I2C_REGISTERED;
    }
    return err;
}

/*
 * ======== tvp5146_cleanup  ========
 */
/* This function is used detach TVP5146 i2c client */
static void tvp5146_cleanup(void)
{
    struct i2c_driver *driver = &tvp5146_i2c_driver;
    if (tvp5146_i2c_registration) {
        i2c_detach_client(&tvp5146_i2c_client);
        i2c_del_driver(driver);
        tvp5146_i2c_client.adapter = NULL;
        tvp5146_i2c_registration = TVP5146_I2C_UNREGISTERED;
    }
}

/*
 * ======== configtvp5146 ========
 */
 
static int configtvp5146(void *arg)
{
    tvp5146_params *tvp5146params = (tvp5146_params *) arg;
    int ret = 0;
    ret |= gpio_set_direction(41,0);
    ret |= __gpio_set(41,1);
    
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x03, 0x69);      //phoenix 2008.01.02 modified

    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x08, 0x00);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x09, 0x80);    
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0a, 0x80);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0b, 0x00);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0c, 0x80);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0d, 0x47);      //phoenix 2008.01.02 modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0F, 0x02);

    ret |= setup656sync(tvp5146params);
    ret |= settvp5146amuxmode(tvp5146params->amuxmode);
    ret |= settvp5146std(tvp5146params->mode);

    return ret;
}

/*
 * ======== clrtvp5146lostlock  ========
 */
static int clrtvp5146lostlock(void)
{
    //TVP5150 Not Support
}

/*
 * ========  enabletvp5146agc ========
 */
static int enabletvp5146agc(int arg)
{
    int ret = 0;
    int agc;
    u8 value;
//    ret = i2c_read_reg(&tvp5146_i2c_client, 0x01, &value);
    
    if (arg == TRUE) {
        agc = 0x01;
    } else {
        agc = 0x00;
    }
//    agc = agc | value;
    
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x01, agc);
        
    return ret;
}

/*
 * ========  gettvpctrl ========
 */
static int getctrl(void *arg)
{
    struct v4l2_control *ctrl = arg;
    int ret = 0;
    u8 value;

    switch (ctrl->id) {
    case V4L2_CID_BRIGHTNESS:
        ret = i2c_read_reg(&tvp5146_i2c_client, 0x09, &value);
        ctrl->value = value;
        break;
    case V4L2_CID_CONTRAST:
        ret = i2c_read_reg(&tvp5146_i2c_client, 0x0C, &value);
        ctrl->value = value;
        break;
    case V4L2_CID_SATURATION:
        ret = i2c_read_reg(&tvp5146_i2c_client, 0x0A, &value);
        ctrl->value = value;
        break;
    case V4L2_CID_HUE:
        ret = i2c_read_reg(&tvp5146_i2c_client, 0x0B, &value);
        ctrl->value = value;
        break;
    case V4L2_CID_AUTOGAIN:
        ret = i2c_read_reg(&tvp5146_i2c_client, 0x01, &value);
        if ((value & 0x3) == 0x01) {
            ctrl->value = TRUE;
        } else {
            ctrl->value = FALSE;
        }
        break;
    default:
        ret = -EINVAL;
        break;
    }
    return ret;
}

/*
 * ========  gettvp5146std ========
 */
static int gettvp5146std(tvp5146_mode * mode)
{
    int ret = 0;
//    u8 output1;
    u8 std;
    u8 lock_status;

    ret |= i2c_read_reg(&tvp5146_i2c_client, 0x28, &std);
    std &= 0xF;
    if(std == TVP5146_MODE_AUTO){
        ret |= i2c_read_reg(&tvp5146_i2c_client, 0x8C, &std);
    //    std    =    std>>1;
    }
    std &= 0xF;    
    *mode = std;    
    ret |= i2c_read_reg(&tvp5146_i2c_client, 0x88, &lock_status);
    if ((lock_status & 0xe) != 0xe) {
        /* not quite locked */
        ret = -EAGAIN;
    }

    return ret;
}

/*
 * ========  gettvp5146status ========
 */

static int gettvp5146status(void *arg)
{
    int ret = 0;
    tvp5146_status *status = (tvp5146_status *) arg;
    u8 agc, brightness, contrast, hue, saturation;
    u8 status_byte;
    u8 std;

    ret = i2c_read_reg(&tvp5146_i2c_client, 0x01, &agc);
    if ((agc & 0x3) == 0x01) {
        status->agc_enable = TRUE;
    } else {
        status->agc_enable = FALSE;
    }
    ret |= i2c_read_reg(&tvp5146_i2c_client, 0x09, &brightness);
    status->brightness = brightness;

    ret |= i2c_read_reg(&tvp5146_i2c_client, 0x0C, &contrast);
    status->contrast = contrast;

    ret |= i2c_read_reg(&tvp5146_i2c_client, 0x0A, &saturation);
    status->saturation = saturation;

    ret |= i2c_read_reg(&tvp5146_i2c_client, 0x0B, &hue);
    status->hue = hue;

    ret |= i2c_read_reg(&tvp5146_i2c_client, 0x88, &status_byte);
    status->field_rate = (status_byte & 0x20) ? 50 : 60;
    status->lost_lock = (status_byte & 0x10) >> 4;
    status->csubc_lock = (status_byte & 0x8) >> 3;
    status->v_lock = (status_byte & 0x4) >> 2;
    status->h_lock = (status_byte & 0x2) >> 1;

    ret |= i2c_read_reg(&tvp5146_i2c_client, 0x8C, &std);
    if (std | 0x80) {    /* auto switch mode */
        status->video_std = TVP5146_MODE_AUTO;
    } else {
        status->video_std = std;
    }
    return ret;
}

/*
 * ======== powerdowntvp5146 ========
 */
static int powerdowntvp5146(int powerdownenable)
{
    u8 powerdownsettings = 0x01;
    int ret = 0;
    u8 value;
    /*Put _tvp5146 in power down mode */
    if (!powerdownenable) {
        powerdownsettings = 0x00;
    }
//    ret = i2c_read_reg(&tvp5146_i2c_client, 0x02, &value);
    
//    powerdownsettings |= value;
    
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x02, powerdownsettings);

    return ret; 
}

/*
 * ======== resettvp5146========
 */
static int resettvp5146(void)
{
    tvp5146_params tvp5146params = { 0 };
    
    dev_dbg(tvp5146_i2c_dev, "\nStarting resettvp5146...");

    int ret = 0;
    ret |= gpio_set_direction(41,0);
    ret |= __gpio_set(41,1);
    
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x03, 0x69);      //phoenix 2008.01.02 modified

    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x08, 0x00);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x09, 0x80);    
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0a, 0x80);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0b, 0x00);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0c, 0x80);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0d, 0x47);      //phoenix 2008.01.02 modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0F, 0x02);
    
    tvp5146params.enablebt656sync = TRUE;
    tvp5146params.data_width = TVP5146_WIDTH_8BIT;

    setup656sync(&tvp5146params);

    settvp5146amuxmode(TVP5146_AMUX_COMPOSITE);
    dev_dbg(tvp5146_i2c_dev, "\nEnd of resettvp5146...");
}

/*
 * ======== queryctrl ========
 */
static int queryctrl(void *arg)
{
    struct v4l2_queryctrl *queryctrl = arg;
    int ret = 0;
    int id = queryctrl->id;

    memset(queryctrl, 0, sizeof(*queryctrl));
    queryctrl->id = id;
    switch (id) {
    case V4L2_CID_BRIGHTNESS:
        strcpy(queryctrl->name, "BRIGHTNESS");
        queryctrl->type = V4L2_CTRL_TYPE_INTEGER;
        queryctrl->minimum = 0;
        queryctrl->maximum = 255;
        queryctrl->step = 1;
        queryctrl->default_value = 128;
        break;
    case V4L2_CID_CONTRAST:
        strcpy(queryctrl->name, "CONTRAST");
        queryctrl->type = V4L2_CTRL_TYPE_INTEGER;
        queryctrl->minimum = 0;
        queryctrl->maximum = 255;
        queryctrl->step = 1;
        queryctrl->default_value = 128;
        break;

    case V4L2_CID_SATURATION:
        strcpy(queryctrl->name, "SATURATION");
        queryctrl->type = V4L2_CTRL_TYPE_INTEGER;
        queryctrl->minimum = 0;
        queryctrl->maximum = 255;
        queryctrl->step = 1;
        queryctrl->default_value = 128;
        break;
    case V4L2_CID_HUE:
        strcpy(queryctrl->name, "HUE");
        queryctrl->type = V4L2_CTRL_TYPE_INTEGER;
        queryctrl->minimum = -128;    /* -180 DEGREE */
        queryctrl->maximum = 127;    /* 180  DEGREE */
        queryctrl->step = 1;
        queryctrl->default_value = 0;    /* 0 DEGREE */
        break;

    case V4L2_CID_AUTOGAIN:
        strcpy(queryctrl->name, "Automatic Gain Control");
        queryctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
        queryctrl->minimum = 0;
        queryctrl->maximum = 1;
        queryctrl->step = 1;
        queryctrl->default_value = 1;
        break;
    default:
        /*if (id < V4L2_CID_LASTP1)
            queryctrl->flags = V4L2_CTRL_FLAG_DISABLED;
        else
            ret = -EINVAL;*/
        break;
    }            /* end switch (id) */
    return ret;
}

/*
 * ======== setctrl ========
 */
static int setctrl(void *arg)
{
    struct v4l2_control *ctrl = arg;
    int ret = 0;

    switch (ctrl->id) {
    case V4L2_CID_BRIGHTNESS:
        ret = settvp5146brightness(ctrl->value);
        break;
    case V4L2_CID_CONTRAST:
        ret = settvp5146contrast(ctrl->value);
        break;
    case V4L2_CID_SATURATION:
        ret = settvp5146saturation(ctrl->value);
        break;
    case V4L2_CID_HUE:
        ret = settvp5146hue(ctrl->value);
        break;
    case V4L2_CID_AUTOGAIN:
        ret = enabletvp5146agc(ctrl->value);
        break;
    default:
        ret = -EINVAL;
        break;
    }
    return ret;
}

/*
 * ======== settvp5146amuxmode ========
 */
static int settvp5146amuxmode(int arg)
{
    u8 input_sel;
    int opmode=0;
    int ret,value;
    if (arg == TVP5146_AMUX_COMPOSITE) {    /* composite */
        input_sel = 0x00;
        opmode=0x30;
    } else if (arg == TVP5146_AMUX_SVIDEO) {    /* s-video */
        input_sel = 0x01;
    } else {
        return -EINVAL;
    }
    
    ret=i2c_write_reg(&tvp5146_i2c_client, 0x02, opmode);
    ret=i2c_write_reg(&tvp5146_i2c_client, 0x00, input_sel);
    
    ret |= i2c_read_reg(&tvp5146_i2c_client, 0x03, &value);
    
    value = (value & ~0x10) | 0x40;
    
    ret=i2c_write_reg(&tvp5146_i2c_client, 0x03, value);
    return ret;
}

/*
 * ======== settvp5146brightness ========
 */
static int settvp5146brightness(int arg)
{
    int ret = 0;
    u8 brightness = (u8) arg;
    ret = i2c_write_reg(&tvp5146_i2c_client, 0x09, brightness);

    return ret;
}

/*
* ======== settvp5146contrast ========
*/
static int settvp5146contrast(int arg)
{
    int ret = 0;
    u8 contrast = (u8) arg;
    ret = i2c_write_reg(&tvp5146_i2c_client, 0x0C, contrast);

    return ret;
}

/*
* ======== settvp5146hue ========
*/
static int settvp5146hue(int arg)
{
    int ret = 0;
    u8 hue = (u8) arg;
    ret = i2c_write_reg(&tvp5146_i2c_client, 0x0C, hue);
    
    return ret;
}

static int settvp5146saturation(int arg)
{
    int ret = 0;
    u8 saturation = (u8) arg;
    ret = i2c_write_reg(&tvp5146_i2c_client, 0x0A, saturation);

    return ret;
}

static int settvp5146std(int arg)
{
    int ret = 0;
    u8 std = (u8) arg & 0xF;    /* the 4th-bit is for squre pixel sampling */

    int fmt=0;
    /* setup the sampling rate: 601 or square pixel */
    debug_print(KERN_INFO "reading i2c registers.\n");

    /* First tests should be against specific std */
    if (std == V4L2_STD_ALL) {
        fmt=0;    /* Autodetect mode */
    } else if (std & V4L2_STD_PAL_M) {
        fmt=0x6;
    } else if (std & (V4L2_STD_PAL_N| V4L2_STD_PAL_Nc)) {
        fmt=0x8;
    } else {
        /* Then, test against generic ones */
        if (std & V4L2_STD_NTSC) {
            fmt=0x2;
        } else if (std & V4L2_STD_PAL) {
            fmt=0x4;
        } else if (std & V4L2_STD_SECAM) {
            fmt=0xc;
        }
    }
    /* setup the video standard */
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x28, fmt);

    /* if autoswitch mode, enable all modes for autoswitch */
    if (std == TVP5146_MODE_AUTO) {
        u8 mask = 0x3C;    /* enable autoswitch for  all standards */
        ret = i2c_write_reg(&tvp5146_i2c_client, 0x04, mask);
    }

    return ret;
}

/*
 * ======== setup656sync ========
 */
  //Un
//static int setup656sync(int enable)
static int setup656sync(tvp5146_params * tvp5146params)
{
    int output1, output2, output3, output4;
    int output5, output6;
    int ret = 0;

        if ((tvp5146params->enablebt656sync)
        && (tvp5146params->data_width == TVP5146_WIDTH_8BIT))  {
        output1 = 0x47;
        output4 = 0xFF;
        output6 = 0;
    } else {
        output1 = 0x40;
        output4 = 0xAF;
        output6 = 0x1E;
    }

    output2 = 0x69;        /* enable clock, enable Y[9:0] */
    output3 = 0x0;
    output5 = 0x4;

    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0D, output1);
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x03, output2);
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0E, output3);
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x36, output4);
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0E, output3);
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x1B, output5);
    //ret |= i2c_write_reg(&tvp5146_i2c_client, 0x1B, output5);
    
    return ret;
}

/*
 * ======== tvp5146_ctrl ========
 */
int tvp5146_ctrl(tvp5146_cmd cmd, void *arg)
{
    int ret = 0;
    switch (cmd) {
    case TVP5146_CONFIG:
        ret = configtvp5146(arg);
        break;
    case TVP5146_RESET:
        ret = resettvp5146();
        break;
    case TVP5146_POWERDOWN:
        ret = powerdowntvp5146(*(int *)arg);
        break;
    case TVP5146_SET_AMUXMODE:
        ret = settvp5146amuxmode(*(int *)arg);
        break;
    case TVP5146_SET_BRIGHTNESS:
        ret = settvp5146brightness(*(int *)arg);
        break;
    case TVP5146_SET_CONTRAST:
        ret = settvp5146contrast(*(int *)arg);
        break;
    case TVP5146_SET_HUE:
        ret = settvp5146hue(*(int *)arg);
        break;
    case TVP5146_SET_SATURATION:
        ret = settvp5146saturation(*(int *)arg);
        break;
    case TVP5146_SET_AGC:
        ret = enabletvp5146agc(*(int *)arg);
        break;
    case TVP5146_SET_VIDEOSTD:
        ret = settvp5146std(*(int *)arg);
        break;
    case TVP5146_CLR_LOSTLOCK:
        ret = clrtvp5146lostlock();
        break;
    case TVP5146_GET_STATUS:
        ret = gettvp5146status(arg);
        break;
    case TVP5146_GET_STD:
        ret = gettvp5146std(arg);
        break;
    case VIDIOC_QUERYCTRL:
        ret = queryctrl(arg);
        break;
    case TVP5146_INIT:
        ret = tvp5146_i2c_init();
        break;
    case VIDIOC_G_CTRL:
        ret = getctrl(arg);
        break;
    case VIDIOC_S_CTRL:
        ret = setctrl(arg);
        break;
    default:
        ret = -EINVAL;
    }
    return ret;
}

static int i2c_read_reg(struct i2c_client *client, u8 reg, u8 * val)
{
    int err = 0;

    struct i2c_msg msg[1];
    unsigned char data[1];

    if (!client->adapter) {
        err = -ENODEV;
    } else {
        msg->addr = client->addr;
        msg->flags = 0;
        msg->len = 1;
        msg->buf = data;
        data[0] = reg;
        err = i2c_transfer(client->adapter, msg, 1);
        if (err >= 0) {
            msg->flags = I2C_M_RD;
            err = i2c_transfer(client->adapter, msg, 1);
            if (err >= 0) {
                *val = data[0];
            }
        }
    }
    return err;
}

static int i2c_write_reg(struct i2c_client *client, u8 reg, u8 val)
{
    int err = 0;

    struct i2c_msg msg[1];
    unsigned char data[2];

    if (!client->adapter) {
        err = -ENODEV;
    } else {
        msg->addr = client->addr;
        msg->flags = 0;
        msg->len = 2;
        msg->buf = data;
        data[0] = reg;
        data[1] = val;
        err = i2c_transfer(client->adapter, msg, 1);
    }
    debug_print(KERN_INFO " i2c data write \n");

    return err;
}

static int _i2c_attach_client(struct i2c_client *client,
                  struct i2c_driver *driver,
                  struct i2c_adapter *adap, int addr)
{
    int err = 0;

    if (client->adapter) {
        err = -EBUSY;    /* our client is already attached */
    } else {
        client->addr = addr;
        client->flags = I2C_CLIENT_ALLOW_USE;
        client->driver = driver;
        client->adapter = adap;

        err = i2c_attach_client(client);
        if (err) {
            client->adapter = NULL;
        }
    }
    return err;
}

static int _i2c_detach_client(struct i2c_client *client)
{
    int err = 0;

    if (!client->adapter) {
        return -ENODEV;    /* our client isn't attached */
    } else {
        err = i2c_detach_client(client);
        client->adapter = NULL;
    }
    return err;
}

static int tvp5146_i2c_probe_adapter(struct i2c_adapter *adap)
{
    int ret;
    ret=_i2c_attach_client(&tvp5146_i2c_client, &tvp5146_i2c_driver,
                  adap, 0x5D);

//    ret |= gpio_set_direction(41,0);             //linger 2007.11.29 GPIO pins are exchanged on 

V1.1
//    ret |= __gpio_set(41,1);
    
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x03, 0x69);      //phoenix 2008.01.02 modified

    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x08, 0x00);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x09, 0x80);    
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0a, 0x80);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0b, 0x00);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0c, 0x80);        //phoenix 2008.01.04 

modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0d, 0x47);      //phoenix 2008.01.02 modified
    ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0F, 0x02);

    return ret;
//end
}
/*
static int tvp5146_i2c_init(void)
{
    int err;
    struct i2c_driver *driver = &tvp5146_i2c_driver;

    driver->owner = THIS_MODULE;
    strlcpy(driver->name, "TVP5150 Video Decoder I2C driver",
        sizeof(driver->name));
    driver->id = I2C_DRIVERID_EXP0;
    driver->flags = I2C_DF_NOTIFY;
    driver->attach_adapter = tvp5146_i2c_probe_adapter;
    driver->detach_client = _i2c_detach_client;

    err = i2c_add_driver(driver);
    if (err) {
        debug_print(KERN_ERR
            "Failed to register TVP5146 I2C client.\n");
    }
    debug_print(KERN_INFO "tvp5146 driver registered.\n");

    return err;
}

static void tvp5146_i2c_cleanup(void)
{
    struct i2c_driver *driver = &tvp5146_i2c_driver;

    i2c_detach_client(&tvp5146_i2c_client);

    i2c_del_driver(driver);
    tvp5146_i2c_client.adapter = NULL;
}
*/
/*
 * ======== tvp5146_i2c_init  ========
 */
/* This function is used initialize TVP5146 i2c client */
static int tvp5146_i2c_init(void)
{
    int err = 0;
    struct i2c_driver *driver = &tvp5146_i2c_driver;

    driver->owner = THIS_MODULE;
    strlcpy(driver->name, "TVP5150 Video Decoder I2C driver",
        sizeof(driver->name));
    driver->id = I2C_DRIVERID_EXP0;
    driver->flags = I2C_DF_NOTIFY;
    driver->attach_adapter = tvp5146_i2c_probe_adapter;
    driver->detach_client = _i2c_detach_client;
    err = i2c_add_driver(driver);
    if (err) {
        debug_print(KERN_ERR
            "Failed to register TVP5150 I2C client.\n");
    }
    debug_print(KERN_INFO "tvp5150 driver registered.\n");
    printk("TVP5150 support for SEED_DVS6446 by Stephen Zhang\n");
    return err;

    return err;
}

/*
 * ======== tvp5146_i2c_cleanup  ========
 */
/* This function is used detach TVP5146 i2c client */
static void tvp5146_i2c_cleanup(void)
{
    struct i2c_driver *driver = &tvp5146_i2c_driver;

    if (tvp5146_i2c_registration) {
        i2c_detach_client(&tvp5146_i2c_client);
        i2c_del_driver(driver);
        tvp5146_i2c_client.adapter = NULL;
        tvp5146_i2c_registration = TVP5146_I2C_UNREGISTERED;
    }
}
//module_init(tvp5146_i2c_init);
module_exit(tvp5146_i2c_cleanup);

EXPORT_SYMBOL(tvp5146_ctrl);
MODULE_LICENSE("GPL");

/**************************************************************************/
/* End of file                                                                            */
/**************************************************************************/

 

 

时间: 2024-08-15 02:33:14

WinCE下的TVP5146调试助手的相关文章

WinCE下的LCD调试助手

    在实际项目中,经常会根据不同应用配备不同大小的LCD.所以需要针对不同的LCD,调节相应的参数.最近的一个项目,先后用了5.6.7和8寸屏,分辨率都是800*480.由于显示驱动是本地驱动,不能够动态卸载和加载.而在相同分辨率的情况下,不同的LCD仅仅是对应的行场同步参数不一样.所以,为了方便调试,针对TCC89平台做了个LCD调试助手,可以在应用程序中直接修改行场同步参数,实时调试LCD.为了验证参数的正确性,简单做了一个用于测试的界面.    LCD调试助手的界面如下图所示,主要提供

WinCE下GPRS拨号连接助手

       这两天在做一个WinCE下的3G拨号助手程序,想起来很早以前调试GPRS模块时做过一个类似的GPRS拨号连接助手,特地找出来存这里,以免以后想用时找不到.有需要的同志也可以下载来看看.                           当时使用的GPRS模块是WaveCom的Q2406A,在S3C2410和PXA270上测试过.这个模块在拨号之前需要做一些配置,用这个工具可以自动完成配置并可以帮助调试GPRS模块,配置完成后,就可以直接双击WinCE网络连接里的拨号连接,连接GP

WinCE下的3G拨号助手

    以前用华为EM730的3G模块时,他们提供了一个拨号软件.刚开始必须用这个拨号软件才能拨号成功,而WinCE控制面板里的拨号连接不能正常工作.后来折腾到WinCE自带的拨号连接也能正常拨号了,主要是修改了注册表中的一些配置.最近又要用电信的Surfing,原厂提供了WinCE下的驱动,拿过来就能用,非常方便.也许以后还得用TD,为了方便调试各种3G上网卡,做了一个3G拨号助手,功能跟WinCE自带的基本一样,增加了移动网号(MNC)和信号强度的自动检测,预置了用户名.密码和域,并能检测当

WinCE-IIC调试助手(S3C2410)

    这两天在调试一款新的硬件平台,它采用的MCU依然是S3C2410.该平台新增了一个RTC模块,采用的芯片是DS1337.这是一个IIC接口的时钟芯片.在开始调试时碰到了一些问题,MCU始终无法与DS1337通讯,走了些弯路,浪费了不少时间.后来发现是IIC的SDA和SCL接反了.为了以后能方便调试2410下的IIC设备,所以决定为2410的WinCE做一个IIC调试助手,以免下次再碰到类似的问题,而多花冤枉时间.       IIC调试助手的主要功能:检测S3C2410 IIC-Bus上

WinCE下串口虚拟软件

    前段时间,介绍了一个WinCE下的串口调试软件Serial Splitter Mobile 3.2.它的主要功能是将一个物理串口克隆成N个,供不同的应用程序使用,以监视物理串口收发的数据.今天介绍一个WinCE下的串口虚拟软件VSPD Mobile 4.2.它的特点是可以创建N对纯虚拟串口,并实现虚拟串口对之间的通讯.很多GPS玩家应该都用过这软件.        VSPD Mobile 4.2使用截图如下:               如上图所示,通过VSPD,创建了一对虚拟串口COM

WinCE驱动调试助手V2.5

     工欲善其事,必先利其器.做WinCE驱动的开发已有一段时间了,WinCE驱动调试助手也跟着更新了很多功能.现在只要做驱动,DM是必须用的.最近在调试WinCE6.0下的驱动,所以又针对WinCE6.0增加了新的功能,也修正了原来的一些BUG.       先介绍一下WinCE驱动调试助手V2.5的功能.驱动调试助手的主要功能是动态加载卸载流驱动,以达到简化驱动调试的目的,节省开发时间,整体分成两部分,注册表操作和驱动调试.       1.注册表操作       V2.5中新增了对整行

WinCE下3G模块的调试

这两天在WinCE6.0上调试了下3G模块,华为的EM730,它支持GPRS和WCDMA.虽然没有涉及到驱动的移植(没有源代码),但调试过程还是几经周折,记下来以便后用. EM730是MINI PCI接口的,也支持USB.于是先请硬件工程师帮忙飞了一堆线,在PC上测试了一下,工作完全正常,证明模块本身没有问题. 在WinCE6.0上,安装了HW提供的一个驱动,并将模块插入,驱动似乎也是正常工作了,没有提示需要再安装驱动.打开串口调试助手,竟然发现多了三个可用的串口,确定驱动是工作起来了.用串口调

WinCE下调试串口的动态复用

      车机项目中用到了很多串口外设,如DVD机芯.GPS.蓝牙.雷达和胎压监测等,而主CPU(TCC89XX)与小MCU(STM32)之间也是通过串口通讯的.一时之间,串口使用有点捉襟见肘的感觉,只能把调试串口拿出来用做普通串口.       调试串口用作普通串口本身没什么问题,之前在S3C2410上也做过.当时是把2410的调试串口强制改为普通串口,系统启动后调试串口就无法正常使用了.但目前的项目仍在进一步完善之中,调试串口还是相当重要的,经常需要通过它,抓一些TRACE来分析和定位问题

WinCE下WIFI模块AR6102的调试

      今天调试了一款SDIO的无线网卡AR6102,由于该芯片是板载的,所以写了一个应用程序,模拟无线网卡的插入拔出,然后简单修改了SDHC驱动,检测应用程序发出的模拟卡插拔的动作,并控制芯片的PWR和RST引脚.幸运的很,改完之后,就可以用了.通过应用程序模拟无线网卡的插入动作后,在超级终端看到了加载无线网卡驱动的打印信息,在控制面板的网络连接里也看到了WIFI设备,AR6K_SD1.       用于测试的无线AP是Cisco的,加密方式是WPA-Personal,根据路由器的设置,选