r3706 - branches/src/target/kernel/2.6.24.x/patches

laforge at sita.openmoko.org laforge at sita.openmoko.org
Thu Dec 20 15:50:01 CET 2007


Author: laforge
Date: 2007-12-20 15:49:59 +0100 (Thu, 20 Dec 2007)
New Revision: 3706

Modified:
   branches/src/target/kernel/2.6.24.x/patches/gta01-jbt6k74.patch
Log:
jbt6k74 cleanup as requested by SPI maintainer
* u_intX_t -> uX
* introduce mutex for tx_buf and reg_cache
* read registers from reg_cache on sysfs read
* add comment why we don't shut down the device on remove()
* fix suspend/resume for non-SUSPEND (i.e. FREEZE/PRETHAW) case
* fix resume: only switch display on if we weren't already in SLEEP/DEEP_STANDBY
* change driver initialization ordering, fail consistent/gracefully


Modified: branches/src/target/kernel/2.6.24.x/patches/gta01-jbt6k74.patch
===================================================================
--- branches/src/target/kernel/2.6.24.x/patches/gta01-jbt6k74.patch	2007-12-20 14:24:37 UTC (rev 3705)
+++ branches/src/target/kernel/2.6.24.x/patches/gta01-jbt6k74.patch	2007-12-20 14:49:59 UTC (rev 3706)
@@ -44,7 +44,7 @@
 ===================================================================
 --- /dev/null
 +++ linux-2.6/drivers/spi/jbt6k74.c
-@@ -0,0 +1,628 @@
+@@ -0,0 +1,673 @@
 +/* Linux kernel driver for the tpo JBT6K74-AS LCM ASIC
 + *
 + * Copyright (C) 2006-2007 by OpenMoko, Inc.
@@ -157,57 +157,68 @@
 +
 +struct jbt_info {
 +	enum jbt_state state, last_state;
-+	u_int16_t tx_buf[8];
 +	struct spi_device *spi_dev;
-+	u_int16_t reg_cache[0xEE];
++	struct mutex lock;		/* protects tx_buf and reg_cache */
++	u16 tx_buf[8];
++	u16 reg_cache[0xEE];
 +};
 +
 +#define JBT_COMMAND	0x000
 +#define JBT_DATA	0x100
 +
-+static int jbt_reg_write_nodata(struct jbt_info *jbt, u_int8_t reg)
++static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
 +{
 +	int rc;
 +
++	mutex_lock(&jbt->lock);
++
 +	jbt->tx_buf[0] = JBT_COMMAND | reg;
-+
-+	rc = spi_write(jbt->spi_dev, (u_int8_t *)jbt->tx_buf,
-+		       1*sizeof(u_int16_t));
++	rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
++		       1*sizeof(u16));
 +	if (rc == 0)
 +		jbt->reg_cache[reg] = 0;
 +
++	mutex_unlock(&jbt->lock);
++
 +	return rc;
 +}
 +
 +
-+static int jbt_reg_write(struct jbt_info *jbt, u_int8_t reg, u_int8_t data)
++static int jbt_reg_write(struct jbt_info *jbt, u8 reg, u8 data)
 +{
 +	int rc;
 +
++	mutex_lock(&jbt->lock);
++
 +	jbt->tx_buf[0] = JBT_COMMAND | reg;
 +	jbt->tx_buf[1] = JBT_DATA | data;
-+
-+	rc = spi_write(jbt->spi_dev, (u_int8_t *)jbt->tx_buf,
-+		       2*sizeof(u_int16_t));
++	rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
++		       2*sizeof(u16));
 +	if (rc == 0)
 +		jbt->reg_cache[reg] = data;
++	
++	mutex_unlock(&jbt->lock);
 +
 +	return rc;
 +}
 +
-+static int jbt_reg_write16(struct jbt_info *jbt, u_int8_t reg, u_int16_t data)
++static int jbt_reg_write16(struct jbt_info *jbt, u8 reg, u16 data)
 +{
 +	int rc;
 +
++	mutex_lock(&jbt->lock);
++
 +	jbt->tx_buf[0] = JBT_COMMAND | reg;
 +	jbt->tx_buf[1] = JBT_DATA | (data >> 8);
 +	jbt->tx_buf[2] = JBT_DATA | (data & 0xff);
 +
-+	rc = spi_write(jbt->spi_dev, (u_int8_t *)jbt->tx_buf,
-+		       3*sizeof(u_int16_t));
++	rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
++		       3*sizeof(u16));
 +	if (rc == 0)
 +		jbt->reg_cache[reg] = data;
 +
++	mutex_unlock(&jbt->lock);
++
 +	return rc;
 +}
 +
@@ -269,7 +280,7 @@
 +		rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2_QVGA, 0x0a);
 +	}
 +
-+	return rc;
++	return rc ? -EIO : 0;
 +}
 +
 +static int standby_to_sleep(struct jbt_info *jbt)
@@ -279,15 +290,15 @@
 +	/* three times command zero */
 +	rc = jbt_reg_write_nodata(jbt, 0x00);
 +	mdelay(1);
-+	rc = jbt_reg_write_nodata(jbt, 0x00);
++	rc |= jbt_reg_write_nodata(jbt, 0x00);
 +	mdelay(1);
-+	rc = jbt_reg_write_nodata(jbt, 0x00);
++	rc |= jbt_reg_write_nodata(jbt, 0x00);
 +	mdelay(1);
 +
 +	/* deep standby out */
 +	rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x17);
 +
-+	return rc;
++	return rc ? -EIO : 0;
 +}
 +
 +static int sleep_to_normal(struct jbt_info *jbt)
@@ -311,7 +322,8 @@
 +
 +	/* initialize register set */
 +	rc |= jbt_init_regs(jbt, 0);
-+	return rc;
++
++	return rc ? -EIO : 0;
 +}
 +
 +static int sleep_to_qvga_normal(struct jbt_info *jbt)
@@ -335,7 +347,8 @@
 +
 +	/* initialize register set for qvga*/
 +	rc |= jbt_init_regs(jbt, 1);
-+	return rc;
++
++	return rc ? -EIO : 0;
 +}
 +
 +static int normal_to_sleep(struct jbt_info *jbt)
@@ -346,7 +359,7 @@
 +	rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0x8002);
 +	rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_IN);
 +
-+	return rc;
++	return rc ? -EIO : 0;
 +}
 +
 +static int sleep_to_standby(struct jbt_info *jbt)
@@ -485,17 +498,21 @@
 +			   const char *buf, size_t count)
 +{
 +	struct jbt_info *jbt = dev_get_drvdata(dev);
-+	int i;
++	int i, rc;
 +
 +	for (i = 0; i < ARRAY_SIZE(jbt_state_names); i++) {
 +		if (!strncmp(buf, jbt_state_names[i],
 +			     strlen(jbt_state_names[i]))) {
-+			jbt6k74_enter_state(jbt, i);
++			rc = jbt6k74_enter_state(jbt, i);
++			if (rc)
++				return rc;
 +			switch (i) {
 +			case JBT_STATE_NORMAL:
 +			case JBT_STATE_QVGA_NORMAL:
 +				/* Enable display again after deep-standby */
-+				jbt6k74_display_onoff(jbt, 1);
++				rc = jbt6k74_display_onoff(jbt, 1);
++				if (rc)
++					return rc;
 +				break;
 +			default:
 +				break;
@@ -524,7 +541,15 @@
 +static ssize_t gamma_read(struct device *dev, struct device_attribute *attr,
 +			  char *buf)
 +{
-+	return strlcpy(buf, "N/A\n", PAGE_SIZE);
++	struct jbt_info *jbt = dev_get_drvdata(dev);
++	int reg = reg_by_string(attr->attr.name);
++	u16 val;
++
++	mutex_lock(&jbt->lock);
++	val = jbt->reg_cache[reg];
++	mutex_unlock(&jbt->lock);
++
++	return sprintf(buf, "0x%04x\n", val);
 +}
 +
 +static ssize_t gamma_write(struct device *dev, struct device_attribute *attr,
@@ -565,17 +590,8 @@
 +	int rc;
 +	struct jbt_info *jbt;
 +
-+	jbt = kzalloc(sizeof(*jbt), GFP_KERNEL);
-+	if (!jbt)
-+		return -ENOMEM;
++	/* the controller doesn't have a MISO pin; we can't do detection */
 +
-+	jbt->spi_dev = spi;
-+	jbt->state = JBT_STATE_DEEP_STANDBY;
-+
-+	/* since we don't have MISO connected, we can't do detection */
-+
-+	dev_set_drvdata(&spi->dev, jbt);
-+
 +	spi->mode = SPI_CPOL | SPI_CPHA;
 +	spi->bits_per_word = 9;
 +
@@ -583,32 +599,58 @@
 +	if (rc < 0) {
 +		dev_err(&spi->dev,
 +			"error during spi_setup of jbt6k74 driver\n");
-+		dev_set_drvdata(&spi->dev, NULL);
-+		kfree(jbt);
 +		return rc;
 +	}
 +
++	jbt = kzalloc(sizeof(*jbt), GFP_KERNEL);
++	if (!jbt)
++		return -ENOMEM;
++
++	jbt->spi_dev = spi;
++	jbt->state = JBT_STATE_DEEP_STANDBY;
++
++	dev_set_drvdata(&spi->dev, jbt);
++
 +	rc = jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
-+	if (rc < 0)
-+		dev_warn(&spi->dev, "cannot enter NORMAL state\n");
++	if (rc < 0) {
++		dev_err(&spi->dev, "cannot enter NORMAL state\n");
++		goto err_free_drvdata;
++	}
 +
-+	jbt6k74_display_onoff(jbt, 1);
++	rc = jbt6k74_display_onoff(jbt, 1);
++	if (rc < 0) {
++		dev_err(&spi->dev, "cannot switch display on\n");
++		goto err_standby;
++	}
 +
 +	rc = sysfs_create_group(&spi->dev.kobj, &jbt_attr_group);
-+	if (rc) {
-+		dev_set_drvdata(&spi->dev, NULL);
-+		kfree(jbt);
-+		return rc;
++	if (rc < 0) {
++		dev_err(&spi->dev, "cannot create sysfs group\n");
++		goto err_off;
 +	}
 +
 +	return 0;
++
++err_off:
++	jbt6k74_display_onoff(jbt, 0);
++err_standby:
++	jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
++err_free_drvdata:
++	dev_set_drvdata(&spi->dev, NULL);
++	kfree(jbt);
++
++	return rc;
 +}
 +
 +static int __devexit jbt_remove(struct spi_device *spi)
 +{
 +	struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
 +
++	/* We don't want to switch off the display in case the user
++	 * accidentially onloads the module (whose use count normally is 0) */
++
 +	sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group);
++	dev_set_drvdata(&spi->dev, NULL);
 +	kfree(jbt);
 +
 +	return 0;
@@ -619,16 +661,11 @@
 +{
 +	struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
 +
-+	switch (state.event) {
-+	case PM_EVENT_SUSPEND:
-+	case 3:
-+		/* Save mode for resume */
-+		jbt->last_state = jbt->state;
-+		jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
-+		return 0;
-+	default:
-+		return -1;
-+	}
++	/* Save mode for resume */
++	jbt->last_state = jbt->state;
++	jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
++
++	return 0;
 +}
 +
 +static int jbt_resume(struct spi_device *spi)
@@ -636,8 +673,16 @@
 +	struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
 +
 +	jbt6k74_enter_state(jbt, jbt->last_state);
-+	jbt6k74_display_onoff(jbt, 1);
 +
++	switch (jbt->last_state) {
++	case JBT_STATE_NORMAL:
++	case JBT_STATE_QVGA_NORMAL:
++		jbt6k74_display_onoff(jbt, 1);
++		break;
++	default:
++		break;
++	}
++
 +	return 0;
 +}
 +#else





More information about the commitlog mailing list