Commit 9cbc6348 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'staging-5.4-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging/IIO driver fixes from Greg KH:
 "Here are some staging and IIO driver fixes for 5.4-rc3.

  The "biggest" thing here is a removal of the fbtft device and flexfb
  code as they have been abandoned by their authors and are no longer
  needed for that hardware.

  Other than that, the usual amount of staging driver and iio driver
  fixes for reported issues, and some speakup sysfs file documentation,
  which has been long awaited for.

  All have been in linux-next with no reported issues"

* tag 'staging-5.4-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (32 commits)
  iio: Fix an undefied reference error in noa1305_probe
  iio: light: opt3001: fix mutex unlock race
  iio: adc: ad799x: fix probe error handling
  iio: light: add missing vcnl4040 of_compatible
  iio: light: fix vcnl4000 devicetree hooks
  iio: imu: st_lsm6dsx: fix waitime for st_lsm6dsx i2c controller
  iio: adc: axp288: Override TS pin bias current for some models
  iio: imu: adis16400: fix memory leak
  iio: imu: adis16400: release allocated memory on failure
  iio: adc: stm32-adc: fix a race when using several adcs with dma and irq
  iio: adc: stm32-adc: move registers definitions
  iio: accel: adxl372: Perform a reset at start up
  iio: accel: adxl372: Fix push to buffers lost samples
  iio: accel: adxl372: Fix/remove limitation for FIFO samples
  iio: adc: hx711: fix bug in sampling of data
  staging: vt6655: Fix memory leak in vt6655_probe
  staging: exfat: Use kvzalloc() instead of kzalloc() for exfat_sb_info
  Staging: fbtft: fix memory leak in fbtft_framebuffer_alloc
  staging: speakup: document sysfs attributes
  staging: rtl8188eu: fix HighestRate check in odm_ARFBRefresh_8188E()
  ...
parents 82c87e7d 3f3d3162
......@@ -474,12 +474,17 @@ static int adxl372_configure_fifo(struct adxl372_state *st)
if (ret < 0)
return ret;
fifo_samples = st->watermark & 0xFF;
/*
* watermark stores the number of sets; we need to write the FIFO
* registers with the number of samples
*/
fifo_samples = (st->watermark * st->fifo_set_size);
fifo_ctl = ADXL372_FIFO_CTL_FORMAT_MODE(st->fifo_format) |
ADXL372_FIFO_CTL_MODE_MODE(st->fifo_mode) |
ADXL372_FIFO_CTL_SAMPLES_MODE(st->watermark);
ADXL372_FIFO_CTL_SAMPLES_MODE(fifo_samples);
ret = regmap_write(st->regmap, ADXL372_FIFO_SAMPLES, fifo_samples);
ret = regmap_write(st->regmap,
ADXL372_FIFO_SAMPLES, fifo_samples & 0xFF);
if (ret < 0)
return ret;
......@@ -548,8 +553,7 @@ static irqreturn_t adxl372_trigger_handler(int irq, void *p)
goto err;
/* Each sample is 2 bytes */
for (i = 0; i < fifo_entries * sizeof(u16);
i += st->fifo_set_size * sizeof(u16))
for (i = 0; i < fifo_entries; i += st->fifo_set_size)
iio_push_to_buffers(indio_dev, &st->fifo_buf[i]);
}
err:
......@@ -571,6 +575,14 @@ static int adxl372_setup(struct adxl372_state *st)
return -ENODEV;
}
/*
* Perform a software reset to make sure the device is in a consistent
* state after start up.
*/
ret = regmap_write(st->regmap, ADXL372_RESET, ADXL372_RESET_CODE);
if (ret < 0)
return ret;
ret = adxl372_set_op_mode(st, ADXL372_STANDBY);
if (ret < 0)
return ret;
......
......@@ -117,7 +117,7 @@
#define BMC150_ACCEL_SLEEP_1_SEC 0x0F
#define BMC150_ACCEL_REG_TEMP 0x08
#define BMC150_ACCEL_TEMP_CENTER_VAL 24
#define BMC150_ACCEL_TEMP_CENTER_VAL 23
#define BMC150_ACCEL_AXIS_TO_REG(axis) (BMC150_ACCEL_REG_XOUT_L + (axis * 2))
#define BMC150_AUTO_SUSPEND_DELAY_MS 2000
......
......@@ -810,10 +810,10 @@ static int ad799x_probe(struct i2c_client *client,
ret = ad799x_write_config(st, st->chip_config->default_config);
if (ret < 0)
goto error_disable_reg;
goto error_disable_vref;
ret = ad799x_read_config(st);
if (ret < 0)
goto error_disable_reg;
goto error_disable_vref;
st->config = ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
......
......@@ -7,6 +7,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/dmi.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
......@@ -25,6 +26,11 @@
#define AXP288_ADC_EN_MASK 0xF0
#define AXP288_ADC_TS_ENABLE 0x01
#define AXP288_ADC_TS_BIAS_MASK GENMASK(5, 4)
#define AXP288_ADC_TS_BIAS_20UA (0 << 4)
#define AXP288_ADC_TS_BIAS_40UA (1 << 4)
#define AXP288_ADC_TS_BIAS_60UA (2 << 4)
#define AXP288_ADC_TS_BIAS_80UA (3 << 4)
#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK GENMASK(1, 0)
#define AXP288_ADC_TS_CURRENT_OFF (0 << 0)
#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING (1 << 0)
......@@ -177,10 +183,36 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
return ret;
}
/*
* We rely on the machine's firmware to correctly setup the TS pin bias current
* at boot. This lists systems with broken fw where we need to set it ourselves.
*/
static const struct dmi_system_id axp288_adc_ts_bias_override[] = {
{
/* Lenovo Ideapad 100S (11 inch) */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 100S-11IBY"),
},
.driver_data = (void *)(uintptr_t)AXP288_ADC_TS_BIAS_80UA,
},
{}
};
static int axp288_adc_initialize(struct axp288_adc_info *info)
{
const struct dmi_system_id *bias_override;
int ret, adc_enable_val;
bias_override = dmi_first_match(axp288_adc_ts_bias_override);
if (bias_override) {
ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
AXP288_ADC_TS_BIAS_MASK,
(uintptr_t)bias_override->driver_data);
if (ret)
return ret;
}
/*
* Determine if the TS pin is enabled and set the TS current-source
* accordingly.
......
......@@ -100,14 +100,14 @@ struct hx711_data {
static int hx711_cycle(struct hx711_data *hx711_data)
{
int val;
unsigned long flags;
/*
* if preempted for more then 60us while PD_SCK is high:
* hx711 is going in reset
* ==> measuring is false
*/
preempt_disable();
local_irq_save(flags);
gpiod_set_value(hx711_data->gpiod_pd_sck, 1);
/*
......@@ -117,7 +117,6 @@ static int hx711_cycle(struct hx711_data *hx711_data)
*/
ndelay(hx711_data->data_ready_delay_ns);
val = gpiod_get_value(hx711_data->gpiod_dout);
/*
* here we are not waiting for 0.2 us as suggested by the datasheet,
* because the oscilloscope showed in a test scenario
......@@ -125,7 +124,7 @@ static int hx711_cycle(struct hx711_data *hx711_data)
* and 0.56 us for PD_SCK low on TI Sitara with 800 MHz
*/
gpiod_set_value(hx711_data->gpiod_pd_sck, 0);
preempt_enable();
local_irq_restore(flags);
/*
* make it a square wave for addressing cases with capacitance on
......@@ -133,7 +132,8 @@ static int hx711_cycle(struct hx711_data *hx711_data)
*/
ndelay(hx711_data->data_ready_delay_ns);
return val;
/* sample as late as possible */
return gpiod_get_value(hx711_data->gpiod_dout);
}
static int hx711_read(struct hx711_data *hx711_data)
......
......@@ -1219,6 +1219,11 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
priv->param->regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
if (!irq)
return -EINVAL;
......@@ -1228,11 +1233,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (ret)
return ret;
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
priv->param->regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
priv->clkin = devm_clk_get(&pdev->dev, "clkin");
if (IS_ERR(priv->clkin)) {
dev_err(&pdev->dev, "failed to get clkin\n");
......
......@@ -24,33 +24,6 @@
#include "stm32-adc-core.h"
/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
#define STM32F4_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04)
/* STM32F4_ADC_CSR - bit fields */
#define STM32F4_EOC3 BIT(17)
#define STM32F4_EOC2 BIT(9)
#define STM32F4_EOC1 BIT(1)
/* STM32F4_ADC_CCR - bit fields */
#define STM32F4_ADC_ADCPRE_SHIFT 16
#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16)
/* STM32H7 - common registers for all ADC instances */
#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
/* STM32H7_ADC_CSR - bit fields */
#define STM32H7_EOC_SLV BIT(18)
#define STM32H7_EOC_MST BIT(2)
/* STM32H7_ADC_CCR - bit fields */
#define STM32H7_PRESC_SHIFT 18
#define STM32H7_PRESC_MASK GENMASK(21, 18)
#define STM32H7_CKMODE_SHIFT 16
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
#define STM32_ADC_CORE_SLEEP_DELAY_MS 2000
/* SYSCFG registers */
......@@ -71,6 +44,8 @@
* @eoc1: adc1 end of conversion flag in @csr
* @eoc2: adc2 end of conversion flag in @csr
* @eoc3: adc3 end of conversion flag in @csr
* @ier: interrupt enable register offset for each adc
* @eocie_msk: end of conversion interrupt enable mask in @ier
*/
struct stm32_adc_common_regs {
u32 csr;
......@@ -78,6 +53,8 @@ struct stm32_adc_common_regs {
u32 eoc1_msk;
u32 eoc2_msk;
u32 eoc3_msk;
u32 ier;
u32 eocie_msk;
};
struct stm32_adc_priv;
......@@ -303,6 +280,8 @@ static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
.eoc1_msk = STM32F4_EOC1,
.eoc2_msk = STM32F4_EOC2,
.eoc3_msk = STM32F4_EOC3,
.ier = STM32F4_ADC_CR1,
.eocie_msk = STM32F4_EOCIE,
};
/* STM32H7 common registers definitions */
......@@ -311,8 +290,24 @@ static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
.ccr = STM32H7_ADC_CCR,
.eoc1_msk = STM32H7_EOC_MST,
.eoc2_msk = STM32H7_EOC_SLV,
.ier = STM32H7_ADC_IER,
.eocie_msk = STM32H7_EOCIE,
};
static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
0, STM32_ADC_OFFSET, STM32_ADC_OFFSET * 2,
};
static unsigned int stm32_adc_eoc_enabled(struct stm32_adc_priv *priv,
unsigned int adc)
{
u32 ier, offset = stm32_adc_offset[adc];
ier = readl_relaxed(priv->common.base + offset + priv->cfg->regs->ier);
return ier & priv->cfg->regs->eocie_msk;
}
/* ADC common interrupt for all instances */
static void stm32_adc_irq_handler(struct irq_desc *desc)
{
......@@ -323,13 +318,28 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
chained_irq_enter(chip, desc);
status = readl_relaxed(priv->common.base + priv->cfg->regs->csr);
if (status & priv->cfg->regs->eoc1_msk)
/*
* End of conversion may be handled by using IRQ or DMA. There may be a
* race here when two conversions complete at the same time on several
* ADCs. EOC may be read 'set' for several ADCs, with:
* - an ADC configured to use DMA (EOC triggers the DMA request, and
* is then automatically cleared by DR read in hardware)
* - an ADC configured to use IRQs (EOCIE bit is set. The handler must
* be called in this case)
* So both EOC status bit in CSR and EOCIE control bit must be checked
* before invoking the interrupt handler (e.g. call ISR only for
* IRQ-enabled ADCs).
*/
if (status & priv->cfg->regs->eoc1_msk &&
stm32_adc_eoc_enabled(priv, 0))
generic_handle_irq(irq_find_mapping(priv->domain, 0));
if (status & priv->cfg->regs->eoc2_msk)
if (status & priv->cfg->regs->eoc2_msk &&
stm32_adc_eoc_enabled(priv, 1))
generic_handle_irq(irq_find_mapping(priv->domain, 1));
if (status & priv->cfg->regs->eoc3_msk)
if (status & priv->cfg->regs->eoc3_msk &&
stm32_adc_eoc_enabled(priv, 2))
generic_handle_irq(irq_find_mapping(priv->domain, 2));
chained_irq_exit(chip, desc);
......
......@@ -25,8 +25,145 @@
* --------------------------------------------------------
*/
#define STM32_ADC_MAX_ADCS 3
#define STM32_ADC_OFFSET 0x100
#define STM32_ADCX_COMN_OFFSET 0x300
/* STM32F4 - Registers for each ADC instance */
#define STM32F4_ADC_SR 0x00
#define STM32F4_ADC_CR1 0x04
#define STM32F4_ADC_CR2 0x08
#define STM32F4_ADC_SMPR1 0x0C
#define STM32F4_ADC_SMPR2 0x10
#define STM32F4_ADC_HTR 0x24
#define STM32F4_ADC_LTR 0x28
#define STM32F4_ADC_SQR1 0x2C
#define STM32F4_ADC_SQR2 0x30
#define STM32F4_ADC_SQR3 0x34
#define STM32F4_ADC_JSQR 0x38
#define STM32F4_ADC_JDR1 0x3C
#define STM32F4_ADC_JDR2 0x40
#define STM32F4_ADC_JDR3 0x44
#define STM32F4_ADC_JDR4 0x48
#define STM32F4_ADC_DR 0x4C
/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
#define STM32F4_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04)
/* STM32F4_ADC_SR - bit fields */
#define STM32F4_STRT BIT(4)
#define STM32F4_EOC BIT(1)
/* STM32F4_ADC_CR1 - bit fields */
#define STM32F4_RES_SHIFT 24
#define STM32F4_RES_MASK GENMASK(25, 24)
#define STM32F4_SCAN BIT(8)
#define STM32F4_EOCIE BIT(5)
/* STM32F4_ADC_CR2 - bit fields */
#define STM32F4_SWSTART BIT(30)
#define STM32F4_EXTEN_SHIFT 28
#define STM32F4_EXTEN_MASK GENMASK(29, 28)
#define STM32F4_EXTSEL_SHIFT 24
#define STM32F4_EXTSEL_MASK GENMASK(27, 24)
#define STM32F4_EOCS BIT(10)
#define STM32F4_DDS BIT(9)
#define STM32F4_DMA BIT(8)
#define STM32F4_ADON BIT(0)
/* STM32F4_ADC_CSR - bit fields */
#define STM32F4_EOC3 BIT(17)
#define STM32F4_EOC2 BIT(9)
#define STM32F4_EOC1 BIT(1)
/* STM32F4_ADC_CCR - bit fields */
#define STM32F4_ADC_ADCPRE_SHIFT 16
#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16)
/* STM32H7 - Registers for each ADC instance */
#define STM32H7_ADC_ISR 0x00
#define STM32H7_ADC_IER 0x04
#define STM32H7_ADC_CR 0x08
#define STM32H7_ADC_CFGR 0x0C
#define STM32H7_ADC_SMPR1 0x14
#define STM32H7_ADC_SMPR2 0x18
#define STM32H7_ADC_PCSEL 0x1C
#define STM32H7_ADC_SQR1 0x30
#define STM32H7_ADC_SQR2 0x34
#define STM32H7_ADC_SQR3 0x38
#define STM32H7_ADC_SQR4 0x3C
#define STM32H7_ADC_DR 0x40
#define STM32H7_ADC_DIFSEL 0xC0
#define STM32H7_ADC_CALFACT 0xC4
#define STM32H7_ADC_CALFACT2 0xC8
/* STM32H7 - common registers for all ADC instances */
#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
/* STM32H7_ADC_ISR - bit fields */
#define STM32MP1_VREGREADY BIT(12)
#define STM32H7_EOC BIT(2)
#define STM32H7_ADRDY BIT(0)
/* STM32H7_ADC_IER - bit fields */
#define STM32H7_EOCIE STM32H7_EOC
/* STM32H7_ADC_CR - bit fields */
#define STM32H7_ADCAL BIT(31)
#define STM32H7_ADCALDIF BIT(30)
#define STM32H7_DEEPPWD BIT(29)
#define STM32H7_ADVREGEN BIT(28)
#define STM32H7_LINCALRDYW6 BIT(27)
#define STM32H7_LINCALRDYW5 BIT(26)
#define STM32H7_LINCALRDYW4 BIT(25)
#define STM32H7_LINCALRDYW3 BIT(24)
#define STM32H7_LINCALRDYW2 BIT(23)
#define STM32H7_LINCALRDYW1 BIT(22)
#define STM32H7_ADCALLIN BIT(16)
#define STM32H7_BOOST BIT(8)
#define STM32H7_ADSTP BIT(4)
#define STM32H7_ADSTART BIT(2)
#define STM32H7_ADDIS BIT(1)
#define STM32H7_ADEN BIT(0)
/* STM32H7_ADC_CFGR bit fields */
#define STM32H7_EXTEN_SHIFT 10
#define STM32H7_EXTEN_MASK GENMASK(11, 10)
#define STM32H7_EXTSEL_SHIFT 5
#define STM32H7_EXTSEL_MASK GENMASK(9, 5)
#define STM32H7_RES_SHIFT 2
#define STM32H7_RES_MASK GENMASK(4, 2)
#define STM32H7_DMNGT_SHIFT 0
#define STM32H7_DMNGT_MASK GENMASK(1, 0)
enum stm32h7_adc_dmngt {
STM32H7_DMNGT_DR_ONLY, /* Regular data in DR only */
STM32H7_DMNGT_DMA_ONESHOT, /* DMA one shot mode */
STM32H7_DMNGT_DFSDM, /* DFSDM mode */
STM32H7_DMNGT_DMA_CIRC, /* DMA circular mode */
};
/* STM32H7_ADC_CALFACT - bit fields */
#define STM32H7_CALFACT_D_SHIFT 16
#define STM32H7_CALFACT_D_MASK GENMASK(26, 16)
#define STM32H7_CALFACT_S_SHIFT 0
#define STM32H7_CALFACT_S_MASK GENMASK(10, 0)
/* STM32H7_ADC_CALFACT2 - bit fields */
#define STM32H7_LINCALFACT_SHIFT 0
#define STM32H7_LINCALFACT_MASK GENMASK(29, 0)
/* STM32H7_ADC_CSR - bit fields */
#define STM32H7_EOC_SLV BIT(18)
#define STM32H7_EOC_MST BIT(2)
/* STM32H7_ADC_CCR - bit fields */
#define STM32H7_PRESC_SHIFT 18
#define STM32H7_PRESC_MASK GENMASK(21, 18)
#define STM32H7_CKMODE_SHIFT 16
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
/**
* struct stm32_adc_common - stm32 ADC driver common data (for all instances)
* @base: control registers base cpu addr
......
......@@ -28,115 +28,6 @@
#include "stm32-adc-core.h"
/* STM32F4 - Registers for each ADC instance */
#define STM32F4_ADC_SR 0x00
#define STM32F4_ADC_CR1 0x04
#define STM32F4_ADC_CR2 0x08
#define STM32F4_ADC_SMPR1 0x0C
#define STM32F4_ADC_SMPR2 0x10
#define STM32F4_ADC_HTR 0x24
#define STM32F4_ADC_LTR 0x28
#define STM32F4_ADC_SQR1 0x2C
#define STM32F4_ADC_SQR2 0x30
#define STM32F4_ADC_SQR3 0x34
#define STM32F4_ADC_JSQR 0x38
#define STM32F4_ADC_JDR1 0x3C
#define STM32F4_ADC_JDR2 0x40
#define STM32F4_ADC_JDR3 0x44
#define STM32F4_ADC_JDR4 0x48
#define STM32F4_ADC_DR 0x4C
/* STM32F4_ADC_SR - bit fields */
#define STM32F4_STRT BIT(4)
#define STM32F4_EOC BIT(1)
/* STM32F4_ADC_CR1 - bit fields */
#define STM32F4_RES_SHIFT 24
#define STM32F4_RES_MASK GENMASK(25, 24)
#define STM32F4_SCAN BIT(8)
#define STM32F4_EOCIE BIT(5)
/* STM32F4_ADC_CR2 - bit fields */
#define STM32F4_SWSTART BIT(30)
#define STM32F4_EXTEN_SHIFT 28
#define STM32F4_EXTEN_MASK GENMASK(29, 28)
#define STM32F4_EXTSEL_SHIFT 24
#define STM32F4_EXTSEL_MASK GENMASK(27, 24)
#define STM32F4_EOCS BIT(10)
#define STM32F4_DDS BIT(9)
#define STM32F4_DMA BIT(8)
#define STM32F4_ADON BIT(0)
/* STM32H7 - Registers for each ADC instance */
#define STM32H7_ADC_ISR 0x00
#define STM32H7_ADC_IER 0x04
#define STM32H7_ADC_CR 0x08
#define STM32H7_ADC_CFGR 0x0C
#define STM32H7_ADC_SMPR1 0x14
#define STM32H7_ADC_SMPR2 0x18
#define STM32H7_ADC_PCSEL 0x1C
#define STM32H7_ADC_SQR1 0x30
#define STM32H7_ADC_SQR2 0x34
#define STM32H7_ADC_SQR3 0x38
#define STM32H7_ADC_SQR4 0x3C
#define STM32H7_ADC_DR 0x40
#define STM32H7_ADC_DIFSEL 0xC0
#define STM32H7_ADC_CALFACT 0xC4
#define STM32H7_ADC_CALFACT2 0xC8
/* STM32H7_ADC_ISR - bit fields */
#define STM32MP1_VREGREADY BIT(12)
#define STM32H7_EOC BIT(2)
#define STM32H7_ADRDY BIT(0)
/* STM32H7_ADC_IER - bit fields */
#define STM32H7_EOCIE STM32H7_EOC
/* STM32H7_ADC_CR - bit fields */
#define STM32H7_ADCAL BIT(31)
#define STM32H7_ADCALDIF BIT(30)
#define STM32H7_DEEPPWD BIT(29)
#define STM32H7_ADVREGEN BIT(28)
#define STM32H7_LINCALRDYW6 BIT(27)
#define STM32H7_LINCALRDYW5 BIT(26)
#define STM32H7_LINCALRDYW4 BIT(25)
#define STM32H7_LINCALRDYW3 BIT(24)
#define STM32H7_LINCALRDYW2 BIT(23)
#define STM32H7_LINCALRDYW1 BIT(22)
#define STM32H7_ADCALLIN BIT(16)
#define STM32H7_BOOST BIT(8)
#define STM32H7_ADSTP BIT(4)
#define STM32H7_ADSTART BIT(2)
#define STM32H7_ADDIS BIT(1)
#define STM32H7_ADEN BIT(0)
/* STM32H7_ADC_CFGR bit fields */
#define STM32H7_EXTEN_SHIFT 10
#define STM32H7_EXTEN_MASK GENMASK(11, 10)
#define STM32H7_EXTSEL_SHIFT 5
#define STM32H7_EXTSEL_MASK GENMASK(9, 5)
#define STM32H7_RES_SHIFT 2
#define STM32H7_RES_MASK GENMASK(4, 2)
#define STM32H7_DMNGT_SHIFT 0
#define STM32H7_DMNGT_MASK GENMASK(1, 0)
enum stm32h7_adc_dmngt {
STM32H7_DMNGT_DR_ONLY, /* Regular data in DR only */
STM32H7_DMNGT_DMA_ONESHOT, /* DMA one shot mode */
STM32H7_DMNGT_DFSDM, /* DFSDM mode */
STM32H7_DMNGT_DMA_CIRC, /* DMA circular mode */
};
/* STM32H7_ADC_CALFACT - bit fields */
#define STM32H7_CALFACT_D_SHIFT 16
#define STM32H7_CALFACT_D_MASK GENMASK(26, 16)
#define STM32H7_CALFACT_S_SHIFT 0
#define STM32H7_CALFACT_S_MASK GENMASK(10, 0)
/* STM32H7_ADC_CALFACT2 - bit fields */
#define STM32H7_LINCALFACT_SHIFT 0
#define STM32H7_LINCALFACT_MASK GENMASK(29, 0)
/* Number of linear calibration shadow registers / LINCALRDYW control bits */
#define STM32H7_LINCALFACT_NUM 6
......
......@@ -35,8 +35,11 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev,
return -ENOMEM;
adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL);
if (!adis->buffer)
if (!adis->buffer) {
kfree(adis->xfer);
adis->xfer = NULL;
return -ENOMEM;
}
tx = adis->buffer + burst_length;
tx[0] = ADIS_READ_REG(adis->burst->reg_cmd);
......@@ -78,8 +81,11 @@ int adis_update_scan_mode(struct iio_dev *indio_dev,
return -ENOMEM;
adis->buffer = kcalloc(indio_dev->scan_bytes, 2, GFP_KERNEL);
if (!adis->buffer)
if (!adis->buffer) {
kfree(adis->xfer);
adis->xfer = NULL;
return -ENOMEM;
}
rx = adis->buffer;
tx = rx + scan_count;
......
......@@ -99,7 +99,9 @@ struct st_lsm6dsx_fs {
#define ST_LSM6DSX_FS_LIST_SIZE 4
struct st_lsm6dsx_fs_table_entry {
struct st_lsm6dsx_reg reg;
struct st_lsm6dsx_fs fs_avl[ST_LSM6DSX_FS_LIST_SIZE];
int fs_len;
};
/**
......
......@@ -145,6 +145,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 },
.fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 },
.fs_avl[3] = { IIO_G_TO_M_S_2(732), 0x1 },
.fs_len = 4,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
......@@ -154,6 +155,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[0] = { IIO_DEGREE_TO_RAD(245), 0x0 },
.fs_avl[1] = { IIO_DEGREE_TO_RAD(500), 0x1 },
.fs_avl[2] = { IIO_DEGREE_TO_RAD(2000), 0x3 },
.fs_len = 3,
},
},
},
......@@ -215,6 +217,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 },
.fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 },
.fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 },
.fs_len = 4,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
......@@ -225,6 +228,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 },
.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 },
.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 },
.fs_len = 4,
},
},
.decimator = {
......@@ -327,6 +331,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 },
.fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 },
.fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 },
.fs_len = 4,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
......@@ -337,6 +342,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 },
.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 },
.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 },
.fs_len = 4,
},
},
.decimator = {
......@@ -448,6 +454,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 },
.fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 },
.fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 },
.fs_len = 4,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
......@@ -458,6 +465,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 },
.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 },
.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 },
.fs_len = 4,
},
},
.decimator = {
......@@ -563,6 +571,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 },
.fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 },
.fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 },
.fs_len = 4,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
......@@ -573,6 +582,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 },
.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 },
.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 },
.fs_len = 4,
},
},
.batch = {
......@@ -693,6 +703,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 },
.fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 },
.fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 },
.fs_len = 4,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
......@@ -703,6 +714,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 },
.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 },
.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 },
.fs_len = 4,
},
},
.batch = {
......@@ -800,6 +812,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 },
.fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 },
.fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 },
.fs_len = 4,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
......@@ -810,6 +823,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 },
.fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 },
.fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 },
.fs_len = 4,
},
},
.batch = {
......@@ -933,11 +947,12 @@ static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor,
int i, err;
fs_table = &sensor->hw->settings->fs_table[sensor->id];
for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++)
for (i = 0; i < fs_table->fs_len; i++) {
if (fs_table->fs_avl[i].gain == gain)
break;
}
if (i == ST_LSM6DSX_FS_LIST_SIZE)
if (i == fs_table->fs_len)
return -EINVAL;
data = ST_LSM6DSX_SHIFT_VAL(fs_table->fs_avl[i].val,
......@@ -1196,18 +1211,13 @@ static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev,
{
struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev));
const struct st_lsm6dsx_fs_table_entry *fs_table;
enum st_lsm6dsx_sensor_id id = sensor->id;
struct st_lsm6dsx_hw *hw = sensor->hw;
int i, len = 0;
fs_table = &hw->settings->fs_table[id];
for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) {
if (!fs_table->fs_avl[i].gain)
break;
fs_table = &hw->settings->fs_table[sensor->id];
for (i = 0; i < fs_table->fs_len; i++)
len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
fs_table->fs_avl[i].gain);
}
buf[len - 1] = '\n';
return len;
......
......@@ -61,6 +61,7 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
.gain = 1500,
.val = 0x0,
}, /* 1500 uG/LSB */
.fs_len = 1,
},
.temp_comp = {
.addr = 0x60,
......@@ -92,9 +93,11 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
{
struct st_lsm6dsx_sensor *sensor;
u16 odr;
sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
msleep((2000U / sensor->odr) + 1);
odr = (hw->enable_mask & BIT(ST_LSM6DSX_ID_ACC)) ? sensor->odr : 13;
msleep((2000U / odr) + 1);
}
/**
......@@ -555,13 +558,9 @@ static ssize_t st_lsm6dsx_shub_scale_avail(struct device *dev,
int i, len = 0;
settings = sensor->ext_info.settings;
for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) {
u16 val = settings->fs_table.fs_avl[i].gain;
if (val > 0)
for (i = 0; i < settings->fs_table.fs_len; i++)
len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
val);
}
settings->fs_table.fs_avl[i].gain);
buf[len - 1] = '\n';
return len;
......
......@@ -314,6 +314,7 @@ config MAX44009
config NOA1305
tristate "ON Semiconductor NOA1305 ambient light sensor"
depends on I2C
select REGMAP_I2C
help
Say Y here if you want to build support for the ON Semiconductor
NOA1305 ambient light sensor.
......
......@@ -686,6 +686,7 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
struct iio_dev *iio = _iio;
struct opt3001 *opt = iio_priv(iio);
int ret;
bool wake_result_ready_queue = false;
if (!opt->ok_to_ignore_lock)
mutex_lock(&opt->lock);
......@@ -720,13 +721,16 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
}
opt->result = ret;
opt->result_ready = true;
wake_up(&opt->result_ready_queue);
wake_result_ready_queue = true;
}
out:
if (!opt->ok_to_ignore_lock)
mutex_unlock(&opt->lock);
if (wake_result_ready_queue)
wake_up(&opt->result_ready_queue);
return IRQ_HANDLED;
}
......
......@@ -398,19 +398,23 @@ static int vcnl4000_probe(struct i2c_client *client,
static const struct of_device_id vcnl_4000_of_match[] = {
{
.compatible = "vishay,vcnl4000",
.data = "VCNL4000",
.data = (void *)VCNL4000,
},
{
.compatible = "vishay,vcnl4010",
.data = "VCNL4010",
.data = (void *)VCNL4010,
},
{
.compatible = "vishay,vcnl4010",
.data = "VCNL4020",
.compatible = "vishay,vcnl4020",
.data = (void *)VCNL4010,
},
{
.compatible = "vishay,vcnl4040",
.data = (void *)VCNL4040,
},
{
.compatible = "vishay,vcnl4200",
.data = "VCNL4200",
.data = (void *)VCNL4200,
},
{},
};
......
# SPDX-License-Identifier: GPL-2.0
config EXFAT_FS
tristate "exFAT fs support"
depends on BLOCK
......@@ -6,7 +7,7 @@ config EXFAT_FS
This adds support for the exFAT file system.
config EXFAT_DONT_MOUNT_VFAT
bool "Prohibit mounting of fat/vfat filesysems by exFAT"
bool "Prohibit mounting of fat/vfat filesystems by exFAT"
depends on EXFAT_FS
default y
help
......
# SPDX-License-Identifier: GPL-2.0
# SPDX-License-Identifier: GPL-2.0-or-later
obj-$(CONFIG_EXFAT_FS) += exfat.o
......
/* SPDX-License-Identifier: GPL-2.0 */
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
......
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
......
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
......
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
......
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
......
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
......@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/pagemap.h>
#include <linux/mpage.h>
......@@ -3450,7 +3451,7 @@ static void exfat_free_super(struct exfat_sb_info *sbi)
kfree(sbi->options.iocharset);
/* mutex_init is in exfat_fill_super function. only for 3.7+ */
mutex_destroy(&sbi->s_lock);
kfree(sbi);
kvfree(sbi);
}
static void exfat_put_super(struct super_block *sb)
......@@ -3845,7 +3846,7 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
* the filesystem, since we're only just about to mount
* it and have no inodes etc active!
*/
sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL);
sbi = kvzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
mutex_init(&sbi->s_lock);
......
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
......
# SPDX-License-Identifier: GPL-2.0
menuconfig FB_TFT
tristate "Support for small TFT LCD display modules"
depends on FB && SPI
depends on FB && SPI && OF
depends on GPIOLIB || COMPILE_TEST
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
......@@ -199,13 +199,3 @@ config FB_TFT_WATTEROTT
depends on FB_TFT
help
Generic Framebuffer support for WATTEROTT
config FB_FLEX
tristate "Generic FB driver for TFT LCD displays"
depends on FB_TFT
help
Generic Framebuffer support for TFT LCD displays.
config FB_TFT_FBTFT_DEVICE
tristate "Module to for adding FBTFT devices"
depends on FB_TFT
......@@ -36,7 +36,3 @@ obj-$(CONFIG_FB_TFT_UC1611) += fb_uc1611.o
obj-$(CONFIG_FB_TFT_UC1701) += fb_uc1701.o
obj-$(CONFIG_FB_TFT_UPD161704) += fb_upd161704.o
obj-$(CONFIG_FB_TFT_WATTEROTT) += fb_watterott.o
obj-$(CONFIG_FB_FLEX) += flexfb.o
# Device modules
obj-$(CONFIG_FB_TFT_FBTFT_DEVICE) += fbtft_device.o
......@@ -714,7 +714,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
if (par->gamma.curves && gamma) {
if (fbtft_gamma_parse_str(par, par->gamma.curves, gamma,
strlen(gamma)))
goto alloc_fail;
goto release_framebuf;
}
/* Transmit buffer */
......@@ -731,7 +731,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
if (txbuflen > 0) {
txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL);
if (!txbuf)
goto alloc_fail;
goto release_framebuf;
par->txbuf.buf = txbuf;
par->txbuf.len = txbuflen;
}
......@@ -753,6 +753,9 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
return info;
release_framebuf:
framebuffer_release(info);
alloc_fail:
vfree(vmem);
......
// SPDX-License-Identifier: GPL-2.0+
/*
*
* Copyright (C) 2013, Noralf Tronnes
*/
#define pr_fmt(fmt) "fbtft_device: " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <video/mipi_display.h>
#include "fbtft.h"
#define MAX_GPIOS 32
static struct spi_device *spi_device;
static struct platform_device *p_device;
static char *name;
module_param(name, charp, 0000);
MODULE_PARM_DESC(name,
"Devicename (required). name=list => list all supported devices.");
static unsigned int rotate;
module_param(rotate, uint, 0000);
MODULE_PARM_DESC(rotate,
"Angle to rotate display counter clockwise: 0, 90, 180, 270");
static unsigned int busnum;
module_param(busnum, uint, 0000);
MODULE_PARM_DESC(busnum, "SPI bus number (default=0)");
static unsigned int cs;
module_param(cs, uint, 0000);
MODULE_PARM_DESC(cs, "SPI chip select (default=0)");
static unsigned int speed;
module_param(speed, uint, 0000);
MODULE_PARM_DESC(speed, "SPI speed (override device default)");
static int mode = -1;
module_param(mode, int, 0000);
MODULE_PARM_DESC(mode, "SPI mode (override device default)");
static unsigned int fps;
module_param(fps, uint, 0000);
MODULE_PARM_DESC(fps, "Frames per second (override driver default)");
static char *gamma;
module_param(gamma, charp, 0000);
MODULE_PARM_DESC(gamma,
"String representation of Gamma Curve(s). Driver specific.");
static int txbuflen;
module_param(txbuflen, int, 0000);
MODULE_PARM_DESC(txbuflen, "txbuflen (override driver default)");
static int bgr = -1;
module_param(bgr, int, 0000);
MODULE_PARM_DESC(bgr,
"BGR bit (supported by some drivers).");
static unsigned int startbyte;
module_param(startbyte, uint, 0000);
MODULE_PARM_DESC(startbyte, "Sets the Start byte used by some SPI displays.");
static bool custom;
module_param(custom, bool, 0000);
MODULE_PARM_DESC(custom, "Add a custom display device. Use speed= argument to make it a SPI device, else platform_device");
static unsigned int width;
module_param(width, uint, 0000);
MODULE_PARM_DESC(width, "Display width, used with the custom argument");
static unsigned int height;
module_param(height, uint, 0000);
MODULE_PARM_DESC(height, "Display height, used with the custom argument");
static unsigned int buswidth = 8;
module_param(buswidth, uint, 0000);
MODULE_PARM_DESC(buswidth, "Display bus width, used with the custom argument");
static s16 init[FBTFT_MAX_INIT_SEQUENCE];
static int init_num;
module_param_array(init, short, &init_num, 0000);
MODULE_PARM_DESC(init, "Init sequence, used with the custom argument");
static unsigned long debug;
module_param(debug, ulong, 0000);
MODULE_PARM_DESC(debug,
"level: 0-7 (the remaining 29 bits is for advanced usage)");
static unsigned int verbose = 3;
module_param(verbose, uint, 0000);
MODULE_PARM_DESC(verbose,
"0 silent, >1 show devices, >2 show devices before (default=3)");
struct fbtft_device_display {
char *name;
struct spi_board_info *spi;
struct platform_device *pdev;
};
static void fbtft_device_pdev_release(struct device *dev);
static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len);
static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
int xs, int ys, int xe, int ye);
#define ADAFRUIT18_GAMMA \
"02 1c 07 12 37 32 29 2d 29 25 2B 39 00 01 03 10\n" \
"03 1d 07 06 2E 2C 29 2D 2E 2E 37 3F 00 00 02 10"
#define CBERRY28_GAMMA \
"D0 00 14 15 13 2C 42 43 4E 09 16 14 18 21\n" \
"D0 00 14 15 13 0B 43 55 53 0C 17 14 23 20"
static const s16 cberry28_init_sequence[] = {
/* turn off sleep mode */
-1, MIPI_DCS_EXIT_SLEEP_MODE,
-2, 120,
/* set pixel format to RGB-565 */
-1, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT,
-1, 0xB2, 0x0C, 0x0C, 0x00, 0x33, 0x33,
/*
* VGH = 13.26V
* VGL = -10.43V
*/
-1, 0xB7, 0x35,
/*
* VDV and VRH register values come from command write
* (instead of NVM)
*/
-1, 0xC2, 0x01, 0xFF,
/*
* VAP = 4.7V + (VCOM + VCOM offset + 0.5 * VDV)
* VAN = -4.7V + (VCOM + VCOM offset + 0.5 * VDV)
*/
-1, 0xC3, 0x17,
/* VDV = 0V */
-1, 0xC4, 0x20,
/* VCOM = 0.675V */
-1, 0xBB, 0x17,
/* VCOM offset = 0V */
-1, 0xC5, 0x20,
/*
* AVDD = 6.8V
* AVCL = -4.8V
* VDS = 2.3V
*/
-1, 0xD0, 0xA4, 0xA1,
-1, MIPI_DCS_SET_DISPLAY_ON,
-3,
};
static const s16 hy28b_init_sequence[] = {
-1, 0x00e7, 0x0010, -1, 0x0000, 0x0001,
-1, 0x0001, 0x0100, -1, 0x0002, 0x0700,
-1, 0x0003, 0x1030, -1, 0x0004, 0x0000,
-1, 0x0008, 0x0207, -1, 0x0009, 0x0000,
-1, 0x000a, 0x0000, -1, 0x000c, 0x0001,
-1, 0x000d, 0x0000, -1, 0x000f, 0x0000,
-1, 0x0010, 0x0000, -1, 0x0011, 0x0007,
-1, 0x0012, 0x0000, -1, 0x0013, 0x0000,
-2, 50, -1, 0x0010, 0x1590, -1, 0x0011,
0x0227, -2, 50, -1, 0x0012, 0x009c, -2, 50,
-1, 0x0013, 0x1900, -1, 0x0029, 0x0023,
-1, 0x002b, 0x000e, -2, 50,
-1, 0x0020, 0x0000, -1, 0x0021, 0x0000,
-2, 50, -1, 0x0050, 0x0000,
-1, 0x0051, 0x00ef, -1, 0x0052, 0x0000,
-1, 0x0053, 0x013f, -1, 0x0060, 0xa700,
-1, 0x0061, 0x0001, -1, 0x006a, 0x0000,
-1, 0x0080, 0x0000, -1, 0x0081, 0x0000,
-1, 0x0082, 0x0000, -1, 0x0083, 0x0000,
-1, 0x0084, 0x0000, -1, 0x0085, 0x0000,
-1, 0x0090, 0x0010, -1, 0x0092, 0x0000,
-1, 0x0093, 0x0003, -1, 0x0095, 0x0110,
-1, 0x0097, 0x0000, -1, 0x0098, 0x0000,
-1, 0x0007, 0x0133, -1, 0x0020, 0x0000,
-1, 0x0021, 0x0000, -2, 100, -3 };
#define HY28B_GAMMA \
"04 1F 4 7 7 0 7 7 6 0\n" \
"0F 00 1 7 4 0 0 0 6 7"
static const s16 pitft_init_sequence[] = {
-1, MIPI_DCS_SOFT_RESET,
-2, 5,
-1, MIPI_DCS_SET_DISPLAY_OFF,
-1, 0xEF, 0x03, 0x80, 0x02,
-1, 0xCF, 0x00, 0xC1, 0x30,
-1, 0xED, 0x64, 0x03, 0x12, 0x81,
-1, 0xE8, 0x85, 0x00, 0x78,
-1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
-1, 0xF7, 0x20,
-1, 0xEA, 0x00, 0x00,
-1, 0xC0, 0x23,
-1, 0xC1, 0x10,
-1, 0xC5, 0x3E, 0x28,
-1, 0xC7, 0x86,
-1, MIPI_DCS_SET_PIXEL_FORMAT, 0x55,
-1, 0xB1, 0x00, 0x18,
-1, 0xB6, 0x08, 0x82, 0x27,
-1, 0xF2, 0x00,
-1, MIPI_DCS_SET_GAMMA_CURVE, 0x01,
-1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E,
0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
-1, 0xE1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31,
0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
-1, MIPI_DCS_EXIT_SLEEP_MODE,
-2, 100,
-1, MIPI_DCS_SET_DISPLAY_ON,
-2, 20,
-3
};
static const s16 waveshare32b_init_sequence[] = {
-1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
-1, 0xCF, 0x00, 0xC1, 0x30,
-1, 0xE8, 0x85, 0x00, 0x78,
-1, 0xEA, 0x00, 0x00,
-1, 0xED, 0x64, 0x03, 0x12, 0x81,
-1, 0xF7, 0x20,
-1, 0xC0, 0x23,
-1, 0xC1, 0x10,
-1, 0xC5, 0x3E, 0x28,
-1, 0xC7, 0x86,
-1, MIPI_DCS_SET_ADDRESS_MODE, 0x28,
-1, MIPI_DCS_SET_PIXEL_FORMAT, 0x55,
-1, 0xB1, 0x00, 0x18,
-1, 0xB6, 0x08, 0x82, 0x27,
-1, 0xF2, 0x00,
-1, MIPI_DCS_SET_GAMMA_CURVE, 0x01,
-1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E,
0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
-1, 0xE1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31,
0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
-1, MIPI_DCS_EXIT_SLEEP_MODE,
-2, 120,
-1, MIPI_DCS_SET_DISPLAY_ON,
-1, MIPI_DCS_WRITE_MEMORY_START,
-3
};
#define PIOLED_GAMMA "0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 " \
"2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 " \
"3 3 3 4 4 4 4 4 4 4 4 4 4 4 4"
/* Supported displays in alphabetical order */
static struct fbtft_device_display displays[] = {
{
.name = "adafruit18",
.spi = &(struct spi_board_info) {
.modalias = "fb_st7735r",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.gamma = ADAFRUIT18_GAMMA,
}
}
}, {
.name = "adafruit18_green",
.spi = &(struct spi_board_info) {
.modalias = "fb_st7735r",
.max_speed_hz = 4000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
.fbtftops.set_addr_win =
adafruit18_green_tab_set_addr_win,
},
.bgr = true,
.gamma = ADAFRUIT18_GAMMA,
}
}
}, {
.name = "adafruit22",
.spi = &(struct spi_board_info) {
.modalias = "fb_hx8340bn",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 9,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "adafruit22a",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9340",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "adafruit28",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9341",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "adafruit13m",
.spi = &(struct spi_board_info) {
.modalias = "fb_ssd1306",
.max_speed_hz = 16000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
}
}
}, {
.name = "admatec_c-berry28",
.spi = &(struct spi_board_info) {
.modalias = "fb_st7789v",
.max_speed_hz = 48000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
.init_sequence = cberry28_init_sequence,
},
.gamma = CBERRY28_GAMMA,
}
}
}, {
.name = "agm1264k-fl",
.pdev = &(struct platform_device) {
.name = "fb_agm1264k-fl",
.id = 0,
.dev = {
.release = fbtft_device_pdev_release,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = FBTFT_ONBOARD_BACKLIGHT,
},
},
}
}
}, {
.name = "dogs102",
.spi = &(struct spi_board_info) {
.modalias = "fb_uc1701",
.max_speed_hz = 8000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
.bgr = true,
}
}
}, {
.name = "er_tftm050_2",
.spi = &(struct spi_board_info) {
.modalias = "fb_ra8875",
.max_speed_hz = 5000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
.width = 480,
.height = 272,
},
.bgr = true,
}
}
}, {
.name = "er_tftm070_5",
.spi = &(struct spi_board_info) {
.modalias = "fb_ra8875",
.max_speed_hz = 5000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
.width = 800,
.height = 480,
},
.bgr = true,
}
}
}, {
.name = "ew24ha0",
.spi = &(struct spi_board_info) {
.modalias = "fb_uc1611",
.max_speed_hz = 32000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
}
}
}, {
.name = "ew24ha0_9bit",
.spi = &(struct spi_board_info) {
.modalias = "fb_uc1611",
.max_speed_hz = 32000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 9,
},
}
}
}, {
.name = "flexfb",
.spi = &(struct spi_board_info) {
.modalias = "flexfb",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
}
}, {
.name = "flexpfb",
.pdev = &(struct platform_device) {
.name = "flexpfb",
.id = 0,
.dev = {
.release = fbtft_device_pdev_release,
}
}
}, {
.name = "freetronicsoled128",
.spi = &(struct spi_board_info) {
.modalias = "fb_ssd1351",
.max_speed_hz = 20000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = FBTFT_ONBOARD_BACKLIGHT,
},
.bgr = true,
}
}
}, {
.name = "hx8353d",
.spi = &(struct spi_board_info) {
.modalias = "fb_hx8353d",
.max_speed_hz = 16000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
}
}
}, {
.name = "hy28a",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9320",
.max_speed_hz = 32000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.startbyte = 0x70,
.bgr = true,
}
}
}, {
.name = "hy28b",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9325",
.max_speed_hz = 48000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
.init_sequence = hy28b_init_sequence,
},
.startbyte = 0x70,
.bgr = true,
.fps = 50,
.gamma = HY28B_GAMMA,
}
}
}, {
.name = "ili9481",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9481",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.regwidth = 16,
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "itdb24",
.pdev = &(struct platform_device) {
.name = "fb_s6d1121",
.id = 0,
.dev = {
.release = fbtft_device_pdev_release,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = false,
},
}
}
}, {
.name = "itdb28",
.pdev = &(struct platform_device) {
.name = "fb_ili9325",
.id = 0,
.dev = {
.release = fbtft_device_pdev_release,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
},
}
}
}, {
.name = "itdb28_spi",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9325",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "mi0283qt-2",
.spi = &(struct spi_board_info) {
.modalias = "fb_hx8347d",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.startbyte = 0x70,
.bgr = true,
}
}
}, {
.name = "mi0283qt-9a",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9341",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 9,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "mi0283qt-v2",
.spi = &(struct spi_board_info) {
.modalias = "fb_watterott",
.max_speed_hz = 4000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
}
}
}, {
.name = "nokia3310",
.spi = &(struct spi_board_info) {
.modalias = "fb_pcd8544",
.max_speed_hz = 400000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
}
}
}, {
.name = "nokia3310a",
.spi = &(struct spi_board_info) {
.modalias = "fb_tls8204",
.max_speed_hz = 1000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
}
}
}, {
.name = "nokia5110",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9163",
.max_speed_hz = 12000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "piscreen",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9486",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.regwidth = 16,
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "pitft",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9340",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.chip_select = 0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
.init_sequence = pitft_init_sequence,
},
.bgr = true,
}
}
}, {
.name = "pioled",
.spi = &(struct spi_board_info) {
.modalias = "fb_ssd1351",
.max_speed_hz = 20000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
.bgr = true,
.gamma = PIOLED_GAMMA
}
}
}, {
.name = "rpi-display",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9341",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "s6d02a1",
.spi = &(struct spi_board_info) {
.modalias = "fb_s6d02a1",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "sainsmart18",
.spi = &(struct spi_board_info) {
.modalias = "fb_st7735r",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
}
}
}, {
.name = "sainsmart32",
.pdev = &(struct platform_device) {
.name = "fb_ssd1289",
.id = 0,
.dev = {
.release = fbtft_device_pdev_release,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 16,
.txbuflen = -2, /* disable buffer */
.backlight = 1,
.fbtftops.write = write_gpio16_wr_slow,
},
.bgr = true,
},
},
}
}, {
.name = "sainsmart32_fast",
.pdev = &(struct platform_device) {
.name = "fb_ssd1289",
.id = 0,
.dev = {
.release = fbtft_device_pdev_release,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 16,
.txbuflen = -2, /* disable buffer */
.backlight = 1,
},
.bgr = true,
},
},
}
}, {
.name = "sainsmart32_latched",
.pdev = &(struct platform_device) {
.name = "fb_ssd1289",
.id = 0,
.dev = {
.release = fbtft_device_pdev_release,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 16,
.txbuflen = -2, /* disable buffer */
.backlight = 1,
.fbtftops.write =
fbtft_write_gpio16_wr_latched,
},
.bgr = true,
},
},
}
}, {
.name = "sainsmart32_spi",
.spi = &(struct spi_board_info) {
.modalias = "fb_ssd1289",
.max_speed_hz = 16000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "spidev",
.spi = &(struct spi_board_info) {
.modalias = "spidev",
.max_speed_hz = 500000,
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
}
}
}, {
.name = "ssd1331",
.spi = &(struct spi_board_info) {
.modalias = "fb_ssd1331",
.max_speed_hz = 20000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
}
}
}, {
.name = "tinylcd35",
.spi = &(struct spi_board_info) {
.modalias = "fb_tinylcd",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "tm022hdh26",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9341",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "tontec35_9481", /* boards before 02 July 2014 */
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9481",
.max_speed_hz = 128000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "tontec35_9486", /* boards after 02 July 2014 */
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9486",
.max_speed_hz = 128000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.bgr = true,
}
}
}, {
.name = "upd161704",
.spi = &(struct spi_board_info) {
.modalias = "fb_upd161704",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
}
}
}, {
.name = "waveshare32b",
.spi = &(struct spi_board_info) {
.modalias = "fb_ili9340",
.max_speed_hz = 48000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
.init_sequence =
waveshare32b_init_sequence,
},
.bgr = true,
}
}
}, {
.name = "waveshare22",
.spi = &(struct spi_board_info) {
.modalias = "fb_bd663474",
.max_speed_hz = 32000000,
.mode = SPI_MODE_3,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
},
}
}
}, {
/* This should be the last item.
* Used with the custom argument
*/
.name = "",
.spi = &(struct spi_board_info) {
.modalias = "",
.max_speed_hz = 0,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
}
},
.pdev = &(struct platform_device) {
.name = "",
.id = 0,
.dev = {
.release = fbtft_device_pdev_release,
.platform_data = &(struct fbtft_platform_data) {
},
},
},
}
};
static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len)
{
u16 data;
int i;
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
static u16 prev_data;
#endif
fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
"%s(len=%zu): ", __func__, len);
while (len) {
data = *(u16 *)buf;
/* Start writing by pulling down /WR */
gpiod_set_value(par->gpio.wr, 0);
/* Set data */
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
if (data == prev_data) {
gpiod_set_value(par->gpio.wr, 0); /* used as delay */
} else {
for (i = 0; i < 16; i++) {
if ((data & 1) != (prev_data & 1))
gpiod_set_value(par->gpio.db[i],
data & 1);
data >>= 1;
prev_data >>= 1;
}
}
#else
for (i = 0; i < 16; i++) {
gpiod_set_value(par->gpio.db[i], data & 1);
data >>= 1;
}
#endif
/* Pullup /WR */
gpiod_set_value(par->gpio.wr, 1);
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
prev_data = *(u16 *)buf;
#endif
buf += 2;
len -= 2;
}
return 0;
}
static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
int xs, int ys, int xe, int ye)
{
write_reg(par, 0x2A, 0, xs + 2, 0, xe + 2);
write_reg(par, 0x2B, 0, ys + 1, 0, ye + 1);
write_reg(par, 0x2C);
}
static void fbtft_device_pdev_release(struct device *dev)
{
/* Needed to silence this message:
* Device 'xxx' does not have a release() function,
* it is broken and must be fixed
*/
}
static int spi_device_found(struct device *dev, void *data)
{
struct spi_device *spi = to_spi_device(dev);
dev_info(dev, "%s %s %dkHz %d bits mode=0x%02X\n", spi->modalias,
dev_name(dev), spi->max_speed_hz / 1000, spi->bits_per_word,
spi->mode);
return 0;
}
static void pr_spi_devices(void)
{
pr_debug("SPI devices registered:\n");
bus_for_each_dev(&spi_bus_type, NULL, NULL, spi_device_found);
}
static int p_device_found(struct device *dev, void *data)
{
struct platform_device
*pdev = to_platform_device(dev);
if (strstr(pdev->name, "fb"))
dev_info(dev, "%s id=%d pdata? %s\n", pdev->name, pdev->id,
pdev->dev.platform_data ? "yes" : "no");
return 0;
}
static void pr_p_devices(void)
{
pr_debug("'fb' Platform devices registered:\n");
bus_for_each_dev(&platform_bus_type, NULL, NULL, p_device_found);
}
#ifdef MODULE
static void fbtft_device_spi_delete(struct spi_master *master, unsigned int cs)
{
struct device *dev;
char str[32];
snprintf(str, sizeof(str), "%s.%u", dev_name(&master->dev), cs);
dev = bus_find_device_by_name(&spi_bus_type, NULL, str);
if (dev) {
if (verbose)
dev_info(dev, "Deleting %s\n", str);
device_del(dev);
}
}
static int fbtft_device_spi_device_register(struct spi_board_info *spi)
{
struct spi_master *master;
master = spi_busnum_to_master(spi->bus_num);
if (!master) {
pr_err("spi_busnum_to_master(%d) returned NULL\n",
spi->bus_num);
return -EINVAL;
}
/* make sure it's available */
fbtft_device_spi_delete(master, spi->chip_select);
spi_device = spi_new_device(master, spi);
put_device(&master->dev);
if (!spi_device) {
dev_err(&master->dev, "spi_new_device() returned NULL\n");
return -EPERM;
}
return 0;
}
#else
static int fbtft_device_spi_device_register(struct spi_board_info *spi)
{
return spi_register_board_info(spi, 1);
}
#endif
static int __init fbtft_device_init(void)
{
struct spi_board_info *spi = NULL;
struct fbtft_platform_data *pdata;
bool found = false;
int i = 0;
int ret = 0;
if (!name) {
#ifdef MODULE
pr_err("missing module parameter: 'name'\n");
return -EINVAL;
#else
return 0;
#endif
}
if (init_num > FBTFT_MAX_INIT_SEQUENCE) {
pr_err("init parameter: exceeded max array size: %d\n",
FBTFT_MAX_INIT_SEQUENCE);
return -EINVAL;
}
if (verbose > 2) {
pr_spi_devices(); /* print list of registered SPI devices */
pr_p_devices(); /* print list of 'fb' platform devices */
}
pr_debug("name='%s', busnum=%d, cs=%d\n", name, busnum, cs);
if (rotate > 0 && rotate < 4) {
rotate = (4 - rotate) * 90;
pr_warn("argument 'rotate' should be an angle. Values 1-3 is deprecated. Setting it to %d.\n",
rotate);
}
if (rotate != 0 && rotate != 90 && rotate != 180 && rotate != 270) {
pr_warn("argument 'rotate' illegal value: %d. Setting it to 0.\n",
rotate);
rotate = 0;
}
/* name=list lists all supported displays */
if (strcmp(name, "list") == 0) {
pr_info("Supported displays:\n");
for (i = 0; i < ARRAY_SIZE(displays); i++)
pr_info("%s\n", displays[i].name);
return -ECANCELED;
}
if (custom) {
i = ARRAY_SIZE(displays) - 1;
displays[i].name = name;
if (speed == 0) {
displays[i].pdev->name = name;
displays[i].spi = NULL;
} else {
size_t len;
len = strlcpy(displays[i].spi->modalias, name,
SPI_NAME_SIZE);
if (len >= SPI_NAME_SIZE)
pr_warn("modalias (name) truncated to: %s\n",
displays[i].spi->modalias);
displays[i].pdev = NULL;
}
}
for (i = 0; i < ARRAY_SIZE(displays); i++) {
if (strncmp(name, displays[i].name, SPI_NAME_SIZE) == 0) {
if (displays[i].spi) {
spi = displays[i].spi;
spi->chip_select = cs;
spi->bus_num = busnum;
if (speed)
spi->max_speed_hz = speed;
if (mode != -1)
spi->mode = mode;
pdata = (void *)spi->platform_data;
} else if (displays[i].pdev) {
p_device = displays[i].pdev;
pdata = p_device->dev.platform_data;
} else {
pr_err("broken displays array\n");
return -EINVAL;
}
pdata->rotate = rotate;
if (bgr == 0)
pdata->bgr = false;
else if (bgr == 1)
pdata->bgr = true;
if (startbyte)
pdata->startbyte = startbyte;
if (gamma)
pdata->gamma = gamma;
pdata->display.debug = debug;
if (fps)
pdata->fps = fps;
if (txbuflen)
pdata->txbuflen = txbuflen;
if (init_num)
pdata->display.init_sequence = init;
if (custom) {
pdata->display.width = width;
pdata->display.height = height;
pdata->display.buswidth = buswidth;
pdata->display.backlight = 1;
}
if (displays[i].spi) {
ret = fbtft_device_spi_device_register(spi);
if (ret) {
pr_err("failed to register SPI device\n");
return ret;
}
} else {
ret = platform_device_register(p_device);
if (ret < 0) {
pr_err("platform_device_register() returned %d\n",
ret);
return ret;
}
}
found = true;
break;
}
}
if (!found) {
pr_err("display not supported: '%s'\n", name);
return -EINVAL;
}
if (spi_device && (verbose > 1))
pr_spi_devices();
if (p_device && (verbose > 1))
pr_p_devices();
return 0;
}
static void __exit fbtft_device_exit(void)
{
if (spi_device) {
device_del(&spi_device->dev);
kfree(spi_device);
}
if (p_device)
platform_device_unregister(p_device);
}
arch_initcall(fbtft_device_init);
module_exit(fbtft_device_exit);
MODULE_DESCRIPTION("Add a FBTFT device.");
MODULE_AUTHOR("Noralf Tronnes");
MODULE_LICENSE("GPL");
// SPDX-License-Identifier: GPL-2.0+
/*
* Generic FB driver for TFT LCD displays
*
* Copyright (C) 2013 Noralf Tronnes
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
#include "fbtft.h"
#define DRVNAME "flexfb"
static char *chip;
module_param(chip, charp, 0000);
MODULE_PARM_DESC(chip, "LCD controller");
static unsigned int width;
module_param(width, uint, 0000);
MODULE_PARM_DESC(width, "Display width");
static unsigned int height;
module_param(height, uint, 0000);
MODULE_PARM_DESC(height, "Display height");
static s16 init[512];
static int init_num;
module_param_array(init, short, &init_num, 0000);
MODULE_PARM_DESC(init, "Init sequence");
static unsigned int setaddrwin;
module_param(setaddrwin, uint, 0000);
MODULE_PARM_DESC(setaddrwin, "Which set_addr_win() implementation to use");
static unsigned int buswidth = 8;
module_param(buswidth, uint, 0000);
MODULE_PARM_DESC(buswidth, "Width of databus (default: 8)");
static unsigned int regwidth = 8;
module_param(regwidth, uint, 0000);
MODULE_PARM_DESC(regwidth, "Width of controller register (default: 8)");
static bool nobacklight;
module_param(nobacklight, bool, 0000);
MODULE_PARM_DESC(nobacklight, "Turn off backlight functionality.");
static bool latched;
module_param(latched, bool, 0000);
MODULE_PARM_DESC(latched, "Use with latched 16-bit databus");
static const s16 *initp;
static int initp_num;
/* default init sequences */
static const s16 st7735r_init[] = {
-1, 0x01,
-2, 150,
-1, 0x11,
-2, 500,
-1, 0xB1, 0x01, 0x2C, 0x2D,
-1, 0xB2, 0x01, 0x2C, 0x2D,
-1, 0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D,
-1, 0xB4, 0x07,
-1, 0xC0, 0xA2, 0x02, 0x84,
-1, 0xC1, 0xC5,
-1, 0xC2, 0x0A, 0x00,
-1, 0xC3, 0x8A, 0x2A,
-1, 0xC4, 0x8A, 0xEE,
-1, 0xC5, 0x0E,
-1, 0x20,
-1, 0x36, 0xC0,
-1, 0x3A, 0x05,
-1, 0xE0, 0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22,
0x1f, 0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10,
-1, 0xE1, 0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e,
0x30, 0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10,
-1, 0x29,
-2, 100,
-1, 0x13,
-2, 10,
-3
};
static const s16 ssd1289_init[] = {
-1, 0x00, 0x0001,
-1, 0x03, 0xA8A4,
-1, 0x0C, 0x0000,
-1, 0x0D, 0x080C,
-1, 0x0E, 0x2B00,
-1, 0x1E, 0x00B7,
-1, 0x01, 0x2B3F,
-1, 0x02, 0x0600,
-1, 0x10, 0x0000,
-1, 0x11, 0x6070,
-1, 0x05, 0x0000,
-1, 0x06, 0x0000,
-1, 0x16, 0xEF1C,
-1, 0x17, 0x0003,
-1, 0x07, 0x0233,
-1, 0x0B, 0x0000,
-1, 0x0F, 0x0000,
-1, 0x41, 0x0000,
-1, 0x42, 0x0000,
-1, 0x48, 0x0000,
-1, 0x49, 0x013F,
-1, 0x4A, 0x0000,
-1, 0x4B, 0x0000,
-1, 0x44, 0xEF00,
-1, 0x45, 0x0000,
-1, 0x46, 0x013F,
-1, 0x30, 0x0707,
-1, 0x31, 0x0204,
-1, 0x32, 0x0204,
-1, 0x33, 0x0502,
-1, 0x34, 0x0507,
-1, 0x35, 0x0204,
-1, 0x36, 0x0204,
-1, 0x37, 0x0502,
-1, 0x3A, 0x0302,
-1, 0x3B, 0x0302,
-1, 0x23, 0x0000,
-1, 0x24, 0x0000,
-1, 0x25, 0x8000,
-1, 0x4f, 0x0000,
-1, 0x4e, 0x0000,
-1, 0x22,
-3
};
static const s16 hx8340bn_init[] = {
-1, 0xC1, 0xFF, 0x83, 0x40,
-1, 0x11,
-2, 150,
-1, 0xCA, 0x70, 0x00, 0xD9,
-1, 0xB0, 0x01, 0x11,
-1, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06,
-2, 20,
-1, 0xC2, 0x60, 0x71, 0x01, 0x0E, 0x05, 0x02, 0x09, 0x31, 0x0A,
-1, 0xC3, 0x67, 0x30, 0x61, 0x17, 0x48, 0x07, 0x05, 0x33,
-2, 10,
-1, 0xB5, 0x35, 0x20, 0x45,
-1, 0xB4, 0x33, 0x25, 0x4C,
-2, 10,
-1, 0x3A, 0x05,
-1, 0x29,
-2, 10,
-3
};
static const s16 ili9225_init[] = {
-1, 0x0001, 0x011C,
-1, 0x0002, 0x0100,
-1, 0x0003, 0x1030,
-1, 0x0008, 0x0808,
-1, 0x000C, 0x0000,
-1, 0x000F, 0x0A01,
-1, 0x0020, 0x0000,
-1, 0x0021, 0x0000,
-2, 50,
-1, 0x0010, 0x0A00,
-1, 0x0011, 0x1038,
-2, 50,
-1, 0x0012, 0x1121,
-1, 0x0013, 0x004E,
-1, 0x0014, 0x676F,
-1, 0x0030, 0x0000,
-1, 0x0031, 0x00DB,
-1, 0x0032, 0x0000,
-1, 0x0033, 0x0000,
-1, 0x0034, 0x00DB,
-1, 0x0035, 0x0000,
-1, 0x0036, 0x00AF,
-1, 0x0037, 0x0000,
-1, 0x0038, 0x00DB,
-1, 0x0039, 0x0000,
-1, 0x0050, 0x0000,
-1, 0x0051, 0x060A,
-1, 0x0052, 0x0D0A,
-1, 0x0053, 0x0303,
-1, 0x0054, 0x0A0D,
-1, 0x0055, 0x0A06,
-1, 0x0056, 0x0000,
-1, 0x0057, 0x0303,
-1, 0x0058, 0x0000,
-1, 0x0059, 0x0000,
-2, 50,
-1, 0x0007, 0x1017,
-2, 50,
-3
};
static const s16 ili9320_init[] = {
-1, 0x00E5, 0x8000,
-1, 0x0000, 0x0001,
-1, 0x0001, 0x0100,
-1, 0x0002, 0x0700,
-1, 0x0003, 0x1030,
-1, 0x0004, 0x0000,
-1, 0x0008, 0x0202,
-1, 0x0009, 0x0000,
-1, 0x000A, 0x0000,
-1, 0x000C, 0x0000,
-1, 0x000D, 0x0000,
-1, 0x000F, 0x0000,
-1, 0x0010, 0x0000,
-1, 0x0011, 0x0007,
-1, 0x0012, 0x0000,
-1, 0x0013, 0x0000,
-2, 200,
-1, 0x0010, 0x17B0,
-1, 0x0011, 0x0031,
-2, 50,
-1, 0x0012, 0x0138,
-2, 50,
-1, 0x0013, 0x1800,
-1, 0x0029, 0x0008,
-2, 50,
-1, 0x0020, 0x0000,
-1, 0x0021, 0x0000,
-1, 0x0030, 0x0000,
-1, 0x0031, 0x0505,
-1, 0x0032, 0x0004,
-1, 0x0035, 0x0006,
-1, 0x0036, 0x0707,
-1, 0x0037, 0x0105,
-1, 0x0038, 0x0002,
-1, 0x0039, 0x0707,
-1, 0x003C, 0x0704,
-1, 0x003D, 0x0807,
-1, 0x0050, 0x0000,
-1, 0x0051, 0x00EF,
-1, 0x0052, 0x0000,
-1, 0x0053, 0x013F,
-1, 0x0060, 0x2700,
-1, 0x0061, 0x0001,
-1, 0x006A, 0x0000,
-1, 0x0080, 0x0000,
-1, 0x0081, 0x0000,
-1, 0x0082, 0x0000,
-1, 0x0083, 0x0000,
-1, 0x0084, 0x0000,
-1, 0x0085, 0x0000,
-1, 0x0090, 0x0010,
-1, 0x0092, 0x0000,
-1, 0x0093, 0x0003,
-1, 0x0095, 0x0110,
-1, 0x0097, 0x0000,
-1, 0x0098, 0x0000,
-1, 0x0007, 0x0173,
-3
};
static const s16 ili9325_init[] = {
-1, 0x00E3, 0x3008,
-1, 0x00E7, 0x0012,
-1, 0x00EF, 0x1231,
-1, 0x0001, 0x0100,
-1, 0x0002, 0x0700,
-1, 0x0003, 0x1030,
-1, 0x0004, 0x0000,
-1, 0x0008, 0x0207,
-1, 0x0009, 0x0000,
-1, 0x000A, 0x0000,
-1, 0x000C, 0x0000,
-1, 0x000D, 0x0000,
-1, 0x000F, 0x0000,
-1, 0x0010, 0x0000,
-1, 0x0011, 0x0007,
-1, 0x0012, 0x0000,
-1, 0x0013, 0x0000,
-2, 200,
-1, 0x0010, 0x1690,
-1, 0x0011, 0x0223,
-2, 50,
-1, 0x0012, 0x000D,
-2, 50,
-1, 0x0013, 0x1200,
-1, 0x0029, 0x000A,
-1, 0x002B, 0x000C,
-2, 50,
-1, 0x0020, 0x0000,
-1, 0x0021, 0x0000,
-1, 0x0030, 0x0000,
-1, 0x0031, 0x0506,
-1, 0x0032, 0x0104,
-1, 0x0035, 0x0207,
-1, 0x0036, 0x000F,
-1, 0x0037, 0x0306,
-1, 0x0038, 0x0102,
-1, 0x0039, 0x0707,
-1, 0x003C, 0x0702,
-1, 0x003D, 0x1604,
-1, 0x0050, 0x0000,
-1, 0x0051, 0x00EF,
-1, 0x0052, 0x0000,
-1, 0x0053, 0x013F,
-1, 0x0060, 0xA700,
-1, 0x0061, 0x0001,
-1, 0x006A, 0x0000,
-1, 0x0080, 0x0000,
-1, 0x0081, 0x0000,
-1, 0x0082, 0x0000,
-1, 0x0083, 0x0000,
-1, 0x0084, 0x0000,
-1, 0x0085, 0x0000,
-1, 0x0090, 0x0010,
-1, 0x0092, 0x0600,
-1, 0x0007, 0x0133,
-3
};
static const s16 ili9341_init[] = {
-1, 0x28,
-2, 20,
-1, 0xCF, 0x00, 0x83, 0x30,
-1, 0xED, 0x64, 0x03, 0x12, 0x81,
-1, 0xE8, 0x85, 0x01, 0x79,
-1, 0xCB, 0x39, 0x2c, 0x00, 0x34, 0x02,
-1, 0xF7, 0x20,
-1, 0xEA, 0x00, 0x00,
-1, 0xC0, 0x26,
-1, 0xC1, 0x11,
-1, 0xC5, 0x35, 0x3E,
-1, 0xC7, 0xBE,
-1, 0xB1, 0x00, 0x1B,
-1, 0xB6, 0x0a, 0x82, 0x27, 0x00,
-1, 0xB7, 0x07,
-1, 0x3A, 0x55,
-1, 0x36, 0x48,
-1, 0x11,
-2, 120,
-1, 0x29,
-2, 20,
-3
};
static const s16 ssd1351_init[] = {
-1, 0xfd, 0x12,
-1, 0xfd, 0xb1,
-1, 0xae,
-1, 0xb3, 0xf1,
-1, 0xca, 0x7f,
-1, 0xa0, 0x74,
-1, 0x15, 0x00, 0x7f,
-1, 0x75, 0x00, 0x7f,
-1, 0xa1, 0x00,
-1, 0xa2, 0x00,
-1, 0xb5, 0x00,
-1, 0xab, 0x01,
-1, 0xb1, 0x32,
-1, 0xb4, 0xa0, 0xb5, 0x55,
-1, 0xbb, 0x17,
-1, 0xbe, 0x05,
-1, 0xc1, 0xc8, 0x80, 0xc8,
-1, 0xc7, 0x0f,
-1, 0xb6, 0x01,
-1, 0xa6,
-1, 0xaf,
-3
};
/**
* struct flexfb_lcd_controller - Describes the LCD controller properties
* @name: Model name of the chip
* @width: Width of display in pixels
* @height: Height of display in pixels
* @setaddrwin: Which set_addr_win() implementation to use
* @regwidth: LCD Controller Register width in bits
* @init_seq: LCD initialization sequence
* @init_seq_sz: Size of LCD initialization sequence
*/
struct flexfb_lcd_controller {
const char *name;
unsigned int width;
unsigned int height;
unsigned int setaddrwin;
unsigned int regwidth;
const s16 *init_seq;
int init_seq_sz;
};
static const struct flexfb_lcd_controller flexfb_chip_table[] = {
{
.name = "st7735r",
.width = 120,
.height = 160,
.init_seq = st7735r_init,
.init_seq_sz = ARRAY_SIZE(st7735r_init),
},
{
.name = "hx8340bn",
.width = 176,
.height = 220,
.init_seq = hx8340bn_init,
.init_seq_sz = ARRAY_SIZE(hx8340bn_init),
},
{
.name = "ili9225",
.width = 176,
.height = 220,
.regwidth = 16,
.init_seq = ili9225_init,
.init_seq_sz = ARRAY_SIZE(ili9225_init),
},
{
.name = "ili9320",
.width = 240,
.height = 320,
.setaddrwin = 1,
.regwidth = 16,
.init_seq = ili9320_init,
.init_seq_sz = ARRAY_SIZE(ili9320_init),
},
{
.name = "ili9325",
.width = 240,
.height = 320,
.setaddrwin = 1,
.regwidth = 16,
.init_seq = ili9325_init,
.init_seq_sz = ARRAY_SIZE(ili9325_init),
},
{
.name = "ili9341",
.width = 240,
.height = 320,
.init_seq = ili9341_init,
.init_seq_sz = ARRAY_SIZE(ili9341_init),
},
{
.name = "ssd1289",
.width = 240,
.height = 320,
.setaddrwin = 2,
.regwidth = 16,
.init_seq = ssd1289_init,
.init_seq_sz = ARRAY_SIZE(ssd1289_init),
},
{
.name = "ssd1351",
.width = 128,
.height = 128,
.setaddrwin = 3,
.init_seq = ssd1351_init,
.init_seq_sz = ARRAY_SIZE(ssd1351_init),
},
};
/* ili9320, ili9325 */
static void flexfb_set_addr_win_1(struct fbtft_par *par,
int xs, int ys, int xe, int ye)
{
switch (par->info->var.rotate) {
/* R20h = Horizontal GRAM Start Address */
/* R21h = Vertical GRAM Start Address */
case 0:
write_reg(par, 0x0020, xs);
write_reg(par, 0x0021, ys);
break;
case 180:
write_reg(par, 0x0020, width - 1 - xs);
write_reg(par, 0x0021, height - 1 - ys);
break;
case 270:
write_reg(par, 0x0020, width - 1 - ys);
write_reg(par, 0x0021, xs);
break;
case 90:
write_reg(par, 0x0020, ys);
write_reg(par, 0x0021, height - 1 - xs);
break;
}
write_reg(par, 0x0022); /* Write Data to GRAM */
}
/* ssd1289 */
static void flexfb_set_addr_win_2(struct fbtft_par *par,
int xs, int ys, int xe, int ye)
{
switch (par->info->var.rotate) {
/* R4Eh - Set GDDRAM X address counter */
/* R4Fh - Set GDDRAM Y address counter */
case 0:
write_reg(par, 0x4e, xs);
write_reg(par, 0x4f, ys);
break;
case 180:
write_reg(par, 0x4e, par->info->var.xres - 1 - xs);
write_reg(par, 0x4f, par->info->var.yres - 1 - ys);
break;
case 270:
write_reg(par, 0x4e, par->info->var.yres - 1 - ys);
write_reg(par, 0x4f, xs);
break;
case 90:
write_reg(par, 0x4e, ys);
write_reg(par, 0x4f, par->info->var.xres - 1 - xs);
break;
}
/* R22h - RAM data write */
write_reg(par, 0x22, 0);
}
/* ssd1351 */
static void set_addr_win_3(struct fbtft_par *par,
int xs, int ys, int xe, int ye)
{
write_reg(par, 0x15, xs, xe);
write_reg(par, 0x75, ys, ye);
write_reg(par, 0x5C);
}
static int flexfb_verify_gpios_dc(struct fbtft_par *par)
{
fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__);
if (!par->gpio.dc) {
dev_err(par->info->device,
"Missing info about 'dc' gpio. Aborting.\n");
return -EINVAL;
}
return 0;
}
static int flexfb_verify_gpios_db(struct fbtft_par *par)
{
int i;
int num_db = buswidth;
fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__);
if (!par->gpio.dc) {
dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n");
return -EINVAL;
}
if (!par->gpio.wr) {
dev_err(par->info->device, "Missing info about 'wr' gpio. Aborting.\n");
return -EINVAL;
}
if (latched && !par->gpio.latch) {
dev_err(par->info->device, "Missing info about 'latch' gpio. Aborting.\n");
return -EINVAL;
}
if (latched)
num_db = buswidth / 2;
for (i = 0; i < num_db; i++) {
if (!par->gpio.db[i]) {
dev_err(par->info->device,
"Missing info about 'db%02d' gpio. Aborting.\n",
i);
return -EINVAL;
}
}
return 0;
}
static void flexfb_chip_load_param(const struct flexfb_lcd_controller *chip)
{
if (!width)
width = chip->width;
if (!height)
height = chip->height;
setaddrwin = chip->setaddrwin;
if (chip->regwidth)
regwidth = chip->regwidth;
if (!init_num) {
initp = chip->init_seq;
initp_num = chip->init_seq_sz;
}
}
static struct fbtft_display flex_display = { };
static int flexfb_chip_init(const struct device *dev)
{
int i;
for (i = 0; i < ARRAY_SIZE(flexfb_chip_table); i++)
if (!strcmp(chip, flexfb_chip_table[i].name)) {
flexfb_chip_load_param(&flexfb_chip_table[i]);
return 0;
}
dev_err(dev, "chip=%s is not supported\n", chip);
return -EINVAL;
}
static int flexfb_probe_common(struct spi_device *sdev,
struct platform_device *pdev)
{
struct device *dev;
struct fb_info *info;
struct fbtft_par *par;
int ret;
initp = init;
initp_num = init_num;
if (sdev)
dev = &sdev->dev;
else
dev = &pdev->dev;
fbtft_init_dbg(dev, "%s(%s)\n", __func__,
sdev ? "'SPI device'" : "'Platform device'");
if (chip) {
ret = flexfb_chip_init(dev);
if (ret)
return ret;
}
if (width == 0 || height == 0) {
dev_err(dev, "argument(s) missing: width and height has to be set.\n");
return -EINVAL;
}
flex_display.width = width;
flex_display.height = height;
fbtft_init_dbg(dev, "Display resolution: %dx%d\n", width, height);
fbtft_init_dbg(dev, "chip = %s\n", chip ? chip : "not set");
fbtft_init_dbg(dev, "setaddrwin = %d\n", setaddrwin);
fbtft_init_dbg(dev, "regwidth = %d\n", regwidth);
fbtft_init_dbg(dev, "buswidth = %d\n", buswidth);
info = fbtft_framebuffer_alloc(&flex_display, dev, dev->platform_data);
if (!info)
return -ENOMEM;
par = info->par;
if (sdev)
par->spi = sdev;
else
par->pdev = pdev;
if (!par->init_sequence)
par->init_sequence = initp;
par->fbtftops.init_display = fbtft_init_display;
/* registerwrite functions */
switch (regwidth) {
case 8:
par->fbtftops.write_register = fbtft_write_reg8_bus8;
break;
case 16:
par->fbtftops.write_register = fbtft_write_reg16_bus8;
break;
default:
dev_err(dev,
"argument 'regwidth': %d is not supported.\n",
regwidth);
return -EINVAL;
}
/* bus functions */
if (sdev) {
par->fbtftops.write = fbtft_write_spi;
switch (buswidth) {
case 8:
par->fbtftops.write_vmem = fbtft_write_vmem16_bus8;
if (!par->startbyte)
par->fbtftops.verify_gpios = flexfb_verify_gpios_dc;
break;
case 9:
if (regwidth == 16) {
dev_err(dev, "argument 'regwidth': %d is not supported with buswidth=%d and SPI.\n",
regwidth, buswidth);
return -EINVAL;
}
par->fbtftops.write_register = fbtft_write_reg8_bus9;
par->fbtftops.write_vmem = fbtft_write_vmem16_bus9;
if (par->spi->master->bits_per_word_mask
& SPI_BPW_MASK(9)) {
par->spi->bits_per_word = 9;
break;
}
dev_warn(dev,
"9-bit SPI not available, emulating using 8-bit.\n");
/* allocate buffer with room for dc bits */
par->extra = devm_kzalloc(par->info->device,
par->txbuf.len
+ (par->txbuf.len / 8) + 8,
GFP_KERNEL);
if (!par->extra) {
ret = -ENOMEM;
goto out_release;
}
par->fbtftops.write = fbtft_write_spi_emulate_9;
break;
default:
dev_err(dev,
"argument 'buswidth': %d is not supported with SPI.\n",
buswidth);
return -EINVAL;
}
} else {
par->fbtftops.verify_gpios = flexfb_verify_gpios_db;
switch (buswidth) {
case 8:
par->fbtftops.write = fbtft_write_gpio8_wr;
par->fbtftops.write_vmem = fbtft_write_vmem16_bus8;
break;
case 16:
par->fbtftops.write_register = fbtft_write_reg16_bus16;
if (latched)
par->fbtftops.write = fbtft_write_gpio16_wr_latched;
else
par->fbtftops.write = fbtft_write_gpio16_wr;
par->fbtftops.write_vmem = fbtft_write_vmem16_bus16;
break;
default:
dev_err(dev,
"argument 'buswidth': %d is not supported with parallel.\n",
buswidth);
return -EINVAL;
}
}
/* set_addr_win function */
switch (setaddrwin) {
case 0:
/* use default */
break;
case 1:
par->fbtftops.set_addr_win = flexfb_set_addr_win_1;
break;
case 2:
par->fbtftops.set_addr_win = flexfb_set_addr_win_2;
break;
case 3:
par->fbtftops.set_addr_win = set_addr_win_3;
break;
default:
dev_err(dev, "argument 'setaddrwin': unknown value %d.\n",
setaddrwin);
return -EINVAL;
}
if (!nobacklight)
par->fbtftops.register_backlight = fbtft_register_backlight;
ret = fbtft_register_framebuffer(info);
if (ret < 0)
goto out_release;
return 0;
out_release:
fbtft_framebuffer_release(info);
return ret;
}
static int flexfb_remove_common(struct device *dev, struct fb_info *info)
{
struct fbtft_par *par;
if (!info)
return -EINVAL;
par = info->par;
if (par)
fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par, "%s()\n",
__func__);
fbtft_unregister_framebuffer(info);
fbtft_framebuffer_release(info);
return 0;
}
static int flexfb_probe_spi(struct spi_device *spi)
{
return flexfb_probe_common(spi, NULL);
}
static int flexfb_remove_spi(struct spi_device *spi)
{
struct fb_info *info = spi_get_drvdata(spi);
return flexfb_remove_common(&spi->dev, info);
}
static int flexfb_probe_pdev(struct platform_device *pdev)
{
return flexfb_probe_common(NULL, pdev);
}
static int flexfb_remove_pdev(struct platform_device *pdev)
{
struct fb_info *info = platform_get_drvdata(pdev);
return flexfb_remove_common(&pdev->dev, info);
}
static struct spi_driver flexfb_spi_driver = {
.driver = {
.name = DRVNAME,
},
.probe = flexfb_probe_spi,
.remove = flexfb_remove_spi,
};
static const struct platform_device_id flexfb_platform_ids[] = {
{ "flexpfb", 0 },
{ },
};
MODULE_DEVICE_TABLE(platform, flexfb_platform_ids);
static struct platform_driver flexfb_platform_driver = {
.driver = {
.name = DRVNAME,
},
.id_table = flexfb_platform_ids,
.probe = flexfb_probe_pdev,
.remove = flexfb_remove_pdev,
};
static int __init flexfb_init(void)
{
int ret, ret2;
ret = spi_register_driver(&flexfb_spi_driver);
ret2 = platform_driver_register(&flexfb_platform_driver);
if (ret < 0)
return ret;
return ret2;
}
static void __exit flexfb_exit(void)
{
spi_unregister_driver(&flexfb_spi_driver);
platform_driver_unregister(&flexfb_platform_driver);
}
/* ------------------------------------------------------------------------- */
module_init(flexfb_init);
module_exit(flexfb_exit);
MODULE_DESCRIPTION("Generic FB driver for TFT LCD displays");
MODULE_AUTHOR("Noralf Tronnes");
MODULE_LICENSE("GPL");
......@@ -261,11 +261,11 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
/* Build the PKO buffer pointer */
hw_buffer.u64 = 0;
if (skb_shinfo(skb)->nr_frags == 0) {
hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)skb->data);
hw_buffer.s.addr = XKPHYS_TO_PHYS((uintptr_t)skb->data);
hw_buffer.s.pool = 0;
hw_buffer.s.size = skb->len;
} else {
hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)skb->data);
hw_buffer.s.addr = XKPHYS_TO_PHYS((uintptr_t)skb->data);
hw_buffer.s.pool = 0;
hw_buffer.s.size = skb_headlen(skb);
CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64;
......@@ -273,11 +273,12 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
skb_frag_t *fs = skb_shinfo(skb)->frags + i;
hw_buffer.s.addr =
XKPHYS_TO_PHYS((u64)skb_frag_address(fs));
XKPHYS_TO_PHYS((uintptr_t)skb_frag_address(fs));
hw_buffer.s.size = skb_frag_size(fs);
CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64;
}
hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)CVM_OCT_SKB_CB(skb));
hw_buffer.s.addr =
XKPHYS_TO_PHYS((uintptr_t)CVM_OCT_SKB_CB(skb));
hw_buffer.s.size = skb_shinfo(skb)->nr_frags + 1;
pko_command.s.segs = skb_shinfo(skb)->nr_frags + 1;
pko_command.s.gather = 1;
......
......@@ -1202,7 +1202,7 @@ static inline int cvmx_wqe_get_grp(cvmx_wqe_t *work)
static inline void *cvmx_phys_to_ptr(uint64_t physical_address)
{
return (void *)(physical_address);
return (void *)(uintptr_t)(physical_address);
}
static inline uint64_t cvmx_ptr_to_phys(void *ptr)
......
......@@ -409,7 +409,7 @@ static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_inf
pRaInfo->PTModeSS = 3;
else if (pRaInfo->HighestRate > 0x0b)
pRaInfo->PTModeSS = 2;
else if (pRaInfo->HighestRate > 0x0b)
else if (pRaInfo->HighestRate > 0x03)
pRaInfo->PTModeSS = 1;
else
pRaInfo->PTModeSS = 0;
......
......@@ -348,8 +348,10 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
}
padapter->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL);
if (!padapter->HalData)
DBG_88E("cant not alloc memory for HAL DATA\n");
if (!padapter->HalData) {
DBG_88E("Failed to allocate memory for HAL data\n");
goto free_adapter;
}
/* step read_chip_version */
rtw_hal_read_chip_version(padapter);
......
What: /sys/accessibility/speakup/attrib_bleep
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Beeps the PC speaker when there is an attribute change such as
foreground or background color when using speakup review
commands. One = on, zero = off.
What: /sys/accessibility/speakup/bell_pos
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This works much like a typewriter bell. If for example 72 is
echoed to bell_pos, it will beep the PC speaker when typing on
a line past character 72.
What: /sys/accessibility/speakup/bleeps
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This controls whether one hears beeps through the PC speaker
when using speakup's review commands.
TODO: what values does it accept?
What: /sys/accessibility/speakup/bleep_time
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This controls the duration of the PC speaker beeps speakup
produces.
TODO: What are the units? Jiffies?
What: /sys/accessibility/speakup/cursor_time
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This controls cursor delay when using arrow keys. When a
connection is very slow, with the default setting, when moving
with the arrows, or backspacing etc. speakup says the incorrect
characters. Set this to a higher value to adjust for the delay
and better synchronisation between cursor position and speech.
What: /sys/accessibility/speakup/delimiters
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Delimit a word from speakup.
TODO: add more info
What: /sys/accessibility/speakup/ex_num
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: TODO:
What: /sys/accessibility/speakup/key_echo
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Controls if speakup speaks keys when they are typed. One = on,
zero = off or don't echo keys.
What: /sys/accessibility/speakup/keymap
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Speakup keymap remaps keys to Speakup functions.
It uses a binary
format. A special program called genmap is needed to compile a
textual keymap into the binary format which is then loaded into
/sys/accessibility/speakup/keymap.
What: /sys/accessibility/speakup/no_interrupt
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Controls if typing interrupts output from speakup. With
no_interrupt set to zero, typing on the keyboard will interrupt
speakup if for example
the say screen command is used before the
entire screen is read.
With no_interrupt set to one, if the say
screen command is used, and one then types on the keyboard,
speakup will continue to say the whole screen regardless until
it finishes.
What: /sys/accessibility/speakup/punc_all
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This is a list of all the punctuation speakup should speak when
punc_level is set to four.
What: /sys/accessibility/speakup/punc_level
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Controls the level of punctuation spoken as the screen is
displayed, not reviewed. Levels range from zero no punctuation,
to four, all punctuation. One corresponds to punc_some, two
corresponds to punc_most, and three as well as four both
correspond to punc_all. Some hardware synthesizers may have
different levels each corresponding to three and four for
punc_level. Also note that if punc_level is set to zero, and
key_echo is set to one, typed punctuation is still spoken as it
is typed.
What: /sys/accessibility/speakup/punc_most
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This is a list of all the punctuation speakup should speak when
punc_level is set to two.
What: /sys/accessibility/speakup/punc_some
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This is a list of all the punctuation speakup should speak when
punc_level is set to one.
What: /sys/accessibility/speakup/reading_punc
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Almost the same as punc_level, the differences being that
reading_punc controls the level of punctuation when reviewing
the screen with speakup's screen review commands. The other
difference is that reading_punc set to three speaks punc_all,
and reading_punc set to four speaks all punctuation, including
spaces.
What: /sys/accessibility/speakup/repeats
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: A list of characters speakup repeats. Normally, when there are
more than three characters in a row, speakup
just reads three of
those characters. For example, "......" would be read as dot,
dot, dot. If a . is added to the list of characters in repeats,
"......" would be read as dot, dot, dot, times six.
What: /sys/accessibility/speakup/say_control
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: If set to one, speakup speaks shift, alt and control when those
keys are pressed. If say_control is set to zero, shift, ctrl,
and alt are not spoken when they are pressed.
What: /sys/accessibility/speakup/say_word_ctl
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: TODO:
What: /sys/accessibility/speakup/silent
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: TODO:
What: /sys/accessibility/speakup/spell_delay
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This controls how fast a word is spelled
when speakup's say word
review command is pressed twice quickly to speak the current
word being reviewed. Zero just speaks the letters one after
another, while values one through four
seem to introduce more of
a pause between the spelling of each letter by speakup.
What: /sys/accessibility/speakup/synth
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Gets or sets the synthesizer driver currently in use. Reading
synth returns the synthesizer driver currently in use. Writing
synth switches to the given synthesizer driver, provided it is
either built into the kernel, or already loaded as a module.
What: /sys/accessibility/speakup/synth_direct
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Sends whatever is written to synth_direct
directly to the speech synthesizer in use, bypassing speakup.
This could be used to make the synthesizer speak
a string, or to
send control sequences to the synthesizer to change how the
synthesizer behaves.
What: /sys/accessibility/speakup/version
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Reading version returns the version of speakup, and the version
of the synthesizer driver currently in use.
What: /sys/accessibility/speakup/i18n/announcements
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This file contains various general announcements, most of which
cannot be categorized. You will find messages such as "You
killed Speakup", "I'm alive", "leaving help", "parked",
"unparked", and others. You will also find the names of the
screen edges and cursor tracking modes here.
What: /sys/accessibility/speakup/i18n/chartab
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: TODO
What: /sys/accessibility/speakup/i18n/ctl_keys
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Here, you will find names of control keys. These are used with
Speakup's say_control feature.
What: /sys/accessibility/speakup/i18n/function_names
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Here, you will find a list of names for Speakup functions.
These are used by the help system. For example, suppose that
you have activated help mode, and you pressed
keypad 3. Speakup
says: "keypad 3 is character, say next."
The message "character, say next" names a Speakup function, and
it comes from this function_names file.
What: /sys/accessibility/speakup/i18n/states
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This file contains names for key states.
Again, these are part of the help system. For instance, if you
had pressed speakup + keypad 3, you would hear:
"speakup keypad 3 is go to bottom edge."
The speakup key is depressed, so the name of the key state is
speakup.
This part of the message comes from the states collection.
What: /sys/accessibility/speakup/i18n/characters
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Through this sys entry, Speakup gives you the ability to change
how Speakup pronounces a given character. You could, for
example, change how some punctuation characters are spoken. You
can even change how Speakup will pronounce certain letters. For
further details see '12. Changing the Pronunciation of
Characters' in Speakup User's Guide (file spkguide.txt in
source).
What: /sys/accessibility/speakup/i18n/colors
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: When you use the "say attributes" function, Speakup says the
name of the foreground and background colors. These names come
from the i18n/colors file.
What: /sys/accessibility/speakup/i18n/formatted
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This group of messages contains embedded formatting codes, to
specify the type and width of displayed data. If you change
these, you must preserve all of the formatting codes, and they
must appear in the order used by the default messages.
What: /sys/accessibility/speakup/i18n/key_names
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Again, key_names is used by Speakup's help system. In the
previous example, Speakup said that you pressed "keypad 3."
This name came from the key_names file.
What: /sys/accessibility/speakup/<synth-name>/
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: In `/sys/accessibility/speakup` is a directory corresponding to
the synthesizer driver currently in use (E.G) `soft` for the
soft driver. This directory contains files which control the
speech synthesizer itself,
as opposed to controlling the speakup
screen reader. The parameters in this directory have the same
names and functions across all
supported synthesizers. The range
of values for freq, pitch, rate, and vol is the same for all
supported synthesizers, with the given range being internally
mapped by the driver to more or less fit the range of values
supported for a given parameter by the individual synthesizer.
Below is a description of values and parameters for soft
synthesizer, which is currently the most commonly used.
What: /sys/accessibility/speakup/soft/caps_start
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This is the string that is sent to the synthesizer to cause it
to start speaking uppercase letters. For the soft synthesizer
and most others, this causes the pitch of the voice to rise
above the currently set pitch.
What: /sys/accessibility/speakup/soft/caps_stop
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This is the string sent to the synthesizer to cause it to stop
speaking uppercase letters. In the case of the soft synthesizer
and most others, this returns the pitch of the voice
down to the
currently set pitch.
What: /sys/accessibility/speakup/soft/delay_time
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: TODO:
What: /sys/accessibility/speakup/soft/direct
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Controls if punctuation is spoken by speakup, or by the
synthesizer.
For example, speakup speaks ">" as "greater", while
the espeak synthesizer used by the soft driver speaks "greater
than". Zero lets speakup speak the punctuation. One lets the
synthesizer itself speak punctuation.
What: /sys/accessibility/speakup/soft/freq
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Gets or sets the frequency of the speech synthesizer. Range is
0-9.
What: /sys/accessibility/speakup/soft/full_time
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: TODO:
What: /sys/accessibility/speakup/soft/jiffy_delta
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This controls how many jiffys the kernel gives to the
synthesizer. Setting this too high can make a system unstable,
or even crash it.
What: /sys/accessibility/speakup/soft/pitch
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Gets or sets the pitch of the synthesizer. The range is 0-9.
What: /sys/accessibility/speakup/soft/punct
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Gets or sets the amount of punctuation spoken by the
synthesizer. The range for the soft driver seems to be 0-2.
TODO: How is this related to speakup's punc_level, or
reading_punc.
What: /sys/accessibility/speakup/soft/rate
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Gets or sets the rate of the synthesizer. Range is from zero
slowest, to nine fastest.
What: /sys/accessibility/speakup/soft/tone
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Gets or sets the tone of the speech synthesizer. The range for
the soft driver seems to be 0-2. This seems to make no
difference if using espeak and the espeakup connector.
TODO: does espeakup support different tonalities?
What: /sys/accessibility/speakup/soft/trigger_time
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: TODO:
What: /sys/accessibility/speakup/soft/voice
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Gets or sets the voice used by the synthesizer if the
synthesizer can speak in more than one voice. The range for the
soft driver is 0-7. Note that while espeak supports multiple
voices, this parameter will not set the voice when the espeakup
connector is used between speakup and espeak.
What: /sys/accessibility/speakup/soft/vol
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: Gets or sets the volume of the speech synthesizer. Range is 0-9,
with zero being the softest, and nine being the loudest.
......@@ -12,7 +12,7 @@
static const struct snd_pcm_hardware snd_bcm2835_playback_hw = {
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
SNDRV_PCM_INFO_SYNC_APPLPTR),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
.rate_min = 8000,
......@@ -29,7 +29,7 @@ static const struct snd_pcm_hardware snd_bcm2835_playback_hw = {
static const struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_DRAIN_TRIGGER | SNDRV_PCM_INFO_SYNC_APPLPTR),
SNDRV_PCM_INFO_SYNC_APPLPTR),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000,
......
......@@ -289,6 +289,7 @@ int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream)
VC_AUDIO_MSG_TYPE_STOP, false);
}
/* FIXME: this doesn't seem working as expected for "draining" */
int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream)
{
struct vc_audio_msg m = {
......
......@@ -1748,8 +1748,10 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
priv->hw->max_signal = 100;
if (vnt_init(priv))
if (vnt_init(priv)) {
device_free_info(priv);
return -ENODEV;
}
device_print_info(priv);
pci_set_drvdata(pcid, priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment