diff --git a/drivers/misc/tsif.c b/drivers/misc/tsif.c index 1ff44685896..b7b1203f781 100644 --- a/drivers/misc/tsif.c +++ b/drivers/misc/tsif.c @@ -140,6 +140,10 @@ struct msm_tsif_device { unsigned int irq; int mode; u32 time_limit; + int clock_inverse; + int data_inverse; + int sync_inverse; + int enable_inverse; enum tsif_state state; struct wake_lock wake_lock; /* clocks */ @@ -358,6 +362,19 @@ static int tsif_start_hw(struct msm_tsif_device *tsif_device) TSIF_STS_CTL_EN_TIME_LIM | TSIF_STS_CTL_EN_TCR | TSIF_STS_CTL_EN_DM; + + if (tsif_device->clock_inverse) + ctl |= TSIF_STS_CTL_INV_CLOCK; + + if (tsif_device->data_inverse) + ctl |= TSIF_STS_CTL_INV_DATA; + + if (tsif_device->sync_inverse) + ctl |= TSIF_STS_CTL_INV_SYNC; + + if (tsif_device->enable_inverse) + ctl |= TSIF_STS_CTL_INV_ENABLE; + dev_info(&tsif_device->pdev->dev, "%s\n", __func__); switch (tsif_device->mode) { case 1: /* mode 1 */ @@ -805,6 +822,10 @@ static ssize_t show_stats(struct device *dev, struct device_attribute *attr, "Client = %p\n" "Pkt/Buf = %d\n" "Pkt/chunk = %d\n" + "Clock inv = %d\n" + "Data inv = %d\n" + "Sync inv = %d\n" + "Enable inv = %d\n" "--statistics--\n" "Rx chunks = %d\n" "Overflow = %d\n" @@ -827,6 +848,10 @@ static ssize_t show_stats(struct device *dev, struct device_attribute *attr, tsif_device->client_data, TSIF_PKTS_IN_BUF, TSIF_PKTS_IN_CHUNK, + tsif_device->clock_inverse, + tsif_device->data_inverse, + tsif_device->sync_inverse, + tsif_device->enable_inverse, tsif_device->stat_rx, tsif_device->stat_overflow, tsif_device->stat_lost_sync, @@ -950,11 +975,120 @@ static ssize_t set_buf_config(struct device *dev, static DEVICE_ATTR(buf_config, S_IRUGO | S_IWUSR, show_buf_config, set_buf_config); +static ssize_t show_clk_inverse(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct msm_tsif_device *tsif_device = dev_get_drvdata(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", tsif_device->clock_inverse); +} + +static ssize_t set_clk_inverse(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct msm_tsif_device *tsif_device = dev_get_drvdata(dev); + int value; + int rc; + if (1 != sscanf(buf, "%d", &value)) { + dev_err(&tsif_device->pdev->dev, + "Failed to parse integer: <%s>\n", buf); + return -EINVAL; + } + rc = tsif_set_clk_inverse(tsif_device, value); + if (!rc) + rc = count; + return rc; +} +static DEVICE_ATTR(clk_inverse, S_IRUGO | S_IWUSR, + show_clk_inverse, set_clk_inverse); + +static ssize_t show_data_inverse(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct msm_tsif_device *tsif_device = dev_get_drvdata(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", tsif_device->data_inverse); +} + +static ssize_t set_data_inverse(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct msm_tsif_device *tsif_device = dev_get_drvdata(dev); + int value; + int rc; + if (1 != sscanf(buf, "%d", &value)) { + dev_err(&tsif_device->pdev->dev, + "Failed to parse integer: <%s>\n", buf); + return -EINVAL; + } + rc = tsif_set_data_inverse(tsif_device, value); + if (!rc) + rc = count; + return rc; +} +static DEVICE_ATTR(data_inverse, S_IRUGO | S_IWUSR, + show_data_inverse, set_data_inverse); + +static ssize_t show_sync_inverse(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct msm_tsif_device *tsif_device = dev_get_drvdata(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", tsif_device->sync_inverse); +} + +static ssize_t set_sync_inverse(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct msm_tsif_device *tsif_device = dev_get_drvdata(dev); + int value; + int rc; + if (1 != sscanf(buf, "%d", &value)) { + dev_err(&tsif_device->pdev->dev, + "Failed to parse integer: <%s>\n", buf); + return -EINVAL; + } + rc = tsif_set_sync_inverse(tsif_device, value); + if (!rc) + rc = count; + return rc; +} +static DEVICE_ATTR(sync_inverse, S_IRUGO | S_IWUSR, + show_sync_inverse, set_sync_inverse); + +static ssize_t show_enable_inverse(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct msm_tsif_device *tsif_device = dev_get_drvdata(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", tsif_device->enable_inverse); +} + +static ssize_t set_enable_inverse(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct msm_tsif_device *tsif_device = dev_get_drvdata(dev); + int value; + int rc; + if (1 != sscanf(buf, "%d", &value)) { + dev_err(&tsif_device->pdev->dev, + "Failed to parse integer: <%s>\n", buf); + return -EINVAL; + } + rc = tsif_set_enable_inverse(tsif_device, value); + if (!rc) + rc = count; + return rc; +} +static DEVICE_ATTR(enable_inverse, S_IRUGO | S_IWUSR, + show_enable_inverse, set_enable_inverse); + + static struct attribute *dev_attrs[] = { &dev_attr_stats.attr, &dev_attr_mode.attr, &dev_attr_time_limit.attr, &dev_attr_buf_config.attr, + &dev_attr_clk_inverse.attr, + &dev_attr_data_inverse.attr, + &dev_attr_sync_inverse.attr, + &dev_attr_enable_inverse.attr, NULL, }; static struct attribute_group dev_attr_grp = { @@ -1287,6 +1421,10 @@ static int __devinit msm_tsif_probe(struct platform_device *pdev) tsif_device->pdev = pdev; platform_set_drvdata(pdev, tsif_device); tsif_device->mode = 1; + tsif_device->clock_inverse = 0; + tsif_device->data_inverse = 0; + tsif_device->sync_inverse = 0; + tsif_device->enable_inverse = 0; tsif_device->pkts_per_chunk = TSIF_PKTS_IN_CHUNK_DEFAULT; tsif_device->chunks_per_buf = TSIF_CHUNKS_IN_BUF_DEFAULT; tasklet_init(&tsif_device->dma_refill, tsif_dma_refill, @@ -1534,6 +1672,78 @@ int tsif_set_buf_config(void *cookie, u32 pkts_in_chunk, u32 chunks_in_buf) } EXPORT_SYMBOL(tsif_set_buf_config); +int tsif_set_clk_inverse(void *cookie, int value) +{ + struct msm_tsif_device *tsif_device = cookie; + if (tsif_device->state != tsif_state_stopped) { + dev_err(&tsif_device->pdev->dev, + "Can't change clock inverse while device is active\n"); + return -EBUSY; + } + if ((value != 0) && (value != 1)) { + dev_err(&tsif_device->pdev->dev, + "Invalid parameter, either 0 or 1: %#x\n", value); + return -EINVAL; + } + tsif_device->clock_inverse = value; + return 0; +} +EXPORT_SYMBOL(tsif_set_clk_inverse); + +int tsif_set_data_inverse(void *cookie, int value) +{ + struct msm_tsif_device *tsif_device = cookie; + if (tsif_device->state != tsif_state_stopped) { + dev_err(&tsif_device->pdev->dev, + "Can't change data inverse while device is active\n"); + return -EBUSY; + } + if ((value != 0) && (value != 1)) { + dev_err(&tsif_device->pdev->dev, + "Invalid parameter, either 0 or 1: %#x\n", value); + return -EINVAL; + } + tsif_device->data_inverse = value; + return 0; +} +EXPORT_SYMBOL(tsif_set_data_inverse); + +int tsif_set_sync_inverse(void *cookie, int value) +{ + struct msm_tsif_device *tsif_device = cookie; + if (tsif_device->state != tsif_state_stopped) { + dev_err(&tsif_device->pdev->dev, + "Can't change sync inverse while device is active\n"); + return -EBUSY; + } + if ((value != 0) && (value != 1)) { + dev_err(&tsif_device->pdev->dev, + "Invalid parameter, either 0 or 1: %#x\n", value); + return -EINVAL; + } + tsif_device->sync_inverse = value; + return 0; +} +EXPORT_SYMBOL(tsif_set_sync_inverse); + +int tsif_set_enable_inverse(void *cookie, int value) +{ + struct msm_tsif_device *tsif_device = cookie; + if (tsif_device->state != tsif_state_stopped) { + dev_err(&tsif_device->pdev->dev, + "Can't change enable inverse while device is active\n"); + return -EBUSY; + } + if ((value != 0) && (value != 1)) { + dev_err(&tsif_device->pdev->dev, + "Invalid parameter, either 0 or 1: %#x\n", value); + return -EINVAL; + } + tsif_device->enable_inverse = value; + return 0; +} +EXPORT_SYMBOL(tsif_set_enable_inverse); + void tsif_get_state(void *cookie, int *ri, int *wi, enum tsif_state *state) { struct msm_tsif_device *tsif_device = cookie; diff --git a/include/linux/tsif_api.h b/include/linux/tsif_api.h index fc4d20b1fa6..0c182282946 100644 --- a/include/linux/tsif_api.h +++ b/include/linux/tsif_api.h @@ -3,8 +3,7 @@ * * Kernel API * - * Copyright (c) 2009-2010, Code Aurora Forum. All rights - * reserved. + * Copyright (c) 2009-2010, 2012, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -124,11 +123,13 @@ int tsif_get_active(void); * Should be called prior to any other tsif_XXX function. */ void *tsif_attach(int id, void (*notify)(void *client_data), void *client_data); + /** * tsif_detach - detach from device * @cookie: TSIF cookie previously obtained with tsif_attach() */ void tsif_detach(void *cookie); + /** * tsif_get_info - get data buffer info * @cookie: TSIF cookie previously obtained with tsif_attach() @@ -140,6 +141,7 @@ void tsif_detach(void *cookie); * using data; since data buffer will be re-allocated on tsif_start() */ void tsif_get_info(void *cookie, void **pdata, int *psize); + /** * tsif_set_mode - set TSIF mode * @cookie: TSIF cookie previously obtained with tsif_attach() @@ -150,6 +152,7 @@ void tsif_get_info(void *cookie, void **pdata, int *psize); * Mode may be changed only when TSIF device is stopped. */ int tsif_set_mode(void *cookie, int mode); + /** * tsif_set_time_limit - set TSIF time limit * @cookie: TSIF cookie previously obtained with tsif_attach() @@ -160,6 +163,7 @@ int tsif_set_mode(void *cookie, int mode); * Time limit may be changed only when TSIF device is stopped. */ int tsif_set_time_limit(void *cookie, u32 value); + /** * tsif_set_buf_config - configure data buffer * @@ -180,6 +184,7 @@ int tsif_set_time_limit(void *cookie, u32 value); * stats */ int tsif_set_buf_config(void *cookie, u32 pkts_in_chunk, u32 chunks_in_buf); + /** * tsif_get_state - query current data buffer information * @cookie: TSIF cookie previously obtained with tsif_attach() @@ -188,6 +193,51 @@ int tsif_set_buf_config(void *cookie, u32 pkts_in_chunk, u32 chunks_in_buf); * @state: if not NULL, state will be stored here */ void tsif_get_state(void *cookie, int *ri, int *wi, enum tsif_state *state); + +/** + * tsif_set_clk_inverse - set whether to inverse the clock signal. + * @cookie: TSIF cookie previously obtained with tsif_attach() + * @inverse: 1 to inverse the clock, 0 otherwise. Default is 0. + * + * Return error code + * + * Setting may be changed only when TSIF device is stopped. + */ +int tsif_set_clk_inverse(void *cookie, int inverse); + +/** + * tsif_set_data_inverse - set whether to inverse the data signal. + * @cookie: TSIF cookie previously obtained with tsif_attach() + * @inverse: 1 to inverse the clock, 0 otherwise. Default is 0. + * + * Return error code + * + * Setting may be changed only when TSIF device is stopped. + */ +int tsif_set_data_inverse(void *cookie, int inverse); + +/** + * tsif_set_sync_inverse - set whether to inverse the sync signal. + * @cookie: TSIF cookie previously obtained with tsif_attach() + * @inverse: 1 to inverse the clock, 0 otherwise. Default is 0. + * + * Return error code + * + * Setting may be changed only when TSIF device is stopped. + */ +int tsif_set_sync_inverse(void *cookie, int inverse); + +/** + * tsif_set_enable_inverse - set whether to inverse the enable signal. + * @cookie: TSIF cookie previously obtained with tsif_attach() + * @inverse: 1 to inverse the clock, 0 otherwise. Default is 0. + * + * Return error code + * + * Setting may be changed only when TSIF device is stopped. + */ +int tsif_set_enable_inverse(void *cookie, int inverse); + /** * tsif_start - start data acquisition * @cookie: TSIF cookie previously obtained with tsif_attach() @@ -195,6 +245,7 @@ void tsif_get_state(void *cookie, int *ri, int *wi, enum tsif_state *state); * Return error code */ int tsif_start(void *cookie); + /** * tsif_stop - stop data acquisition * @cookie: TSIF cookie previously obtained with tsif_attach() @@ -203,6 +254,7 @@ int tsif_start(void *cookie); * query data buffer info using tsif_get_info() and reset its data pointers. */ void tsif_stop(void *cookie); + /** * tsif_reclaim_packets - inform that buffer space may be reclaimed * @cookie: TSIF cookie previously obtained with tsif_attach()