in drivers/lcd/ft80x.c [630:1147]
static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
FAR struct inode *inode;
FAR struct ft80x_dev_s *priv;
int ret;
inode = filep->f_inode;
DEBUGASSERT(inode->i_private != NULL);
priv = inode->i_private;
lcdinfo("cmd: %d arg: %lu\n", cmd, arg);
/* Get exclusive access to the device structures */
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return ret;
}
/* Handle built-in ioctl commands */
switch (cmd)
{
/* FT80X_IOC_CREATEDL:
* Description: Write a display list to the FT80x display list
* memory
* Description: Write a display list to the FT80x display list
* memory starting at offset zero. This may or may
* not be the entire display list. Display lists may
* be created incrementally, starting with
* FT80X_IOC_CREATEDL and finishing the display list
* using FT80XIO_APPENDDL
* Argument: A reference to a display list structure instance.
* See struct ft80x_displaylist_s.
* Returns: None
*/
case FT80X_IOC_CREATEDL:
/* Set the file position to zero and fall through to "append" the new
* display list data at offset 0.
*/
filep->f_pos = 0;
/* FALLTHROUGH */
/* FT80X_IOC_APPENDDL:
* Description: Write additional display list entries to the FT80x
* display list memory at the current display list
* offset. This IOCTL command permits display lists
* to be completed incrementally, starting with
* FT80X_IOC_CREATEDL and finishing the display list
* using FT80XIO_APPENDDL.
* Argument: A reference to a display list structure instance.
* See struct ft80x_displaylist_s.
* Returns: None
*/
case FT80X_IOC_APPENDDL:
{
FAR struct ft80x_displaylist_s *dl =
(FAR struct ft80x_displaylist_s *)((uintptr_t)arg);
if (dl == NULL || ((uintptr_t)&dl->cmd & 3) != 0 ||
(dl->dlsize & 3) != 0 ||
dl->dlsize + filep->f_pos > FT80X_RAM_DL_SIZE)
{
ret = -EINVAL;
}
else
{
/* Check if there is a display list. It might be useful for
* the application to issue FT80X_IOC_CREATEDL with no data in
* order to initialize the display list, then form all of the
* list entries with FT80X_IOC_APPENDDL.
*/
if (dl->dlsize > 0)
{
/* This IOCTL command simply copies the display list
* provided into the FT80x display list memory.
*/
ft80x_write_memory(priv, FT80X_RAM_DL + filep->f_pos,
&dl->cmd, dl->dlsize);
filep->f_pos += dl->dlsize;
}
ret = OK;
}
}
break;
/* FT80X_IOC_GETRAMDL:
* Description: Read a 32-bit value from the display list.
* Argument: A reference to an instance of struct ft80x_relmem_s.
* Returns: The 32-bit value read from the display list.
*/
case FT80X_IOC_GETRAMDL:
{
FAR struct ft80x_relmem_s *ramdl =
(FAR struct ft80x_relmem_s *)((uintptr_t)arg);
if (ramdl == NULL || ((uintptr_t)ramdl->offset & 3) != 0 ||
ramdl->offset >= FT80X_RAM_DL_SIZE)
{
ret = -EINVAL;
}
else
{
ft80x_read_memory(priv, FT80X_RAM_DL + ramdl->offset,
ramdl->value, ramdl->nbytes);
ret = OK;
}
}
break;
/* FT80X_IOC_PUTRAMG
* Description: Write byte data to FT80x graphics memory (RAM_G)
* Argument: A reference to an instance of struct ft80x_relmem_s.
* Returns: None.
*/
case FT80X_IOC_PUTRAMG:
{
FAR struct ft80x_relmem_s *ramg =
(FAR struct ft80x_relmem_s *)((uintptr_t)arg);
if (ramg == NULL ||
(ramg->offset + ramg->nbytes) >= FT80X_RAM_G_SIZE)
{
ret = -EINVAL;
}
else
{
ft80x_write_memory(priv, FT80X_RAM_G + ramg->offset,
ramg->value, ramg->nbytes);
ret = OK;
}
}
break;
/* FT80X_IOC_PUTRAMCMD
* Description: Write 32-bit aligned data to FT80x FIFO (RAM_CMD)
* Argument: A reference to an instance of struct ft80x_relmem_s.
* Returns: None.
*/
case FT80X_IOC_PUTRAMCMD:
{
FAR struct ft80x_relmem_s *ramcmd =
(FAR struct ft80x_relmem_s *)((uintptr_t)arg);
if (ramcmd == NULL || ((uintptr_t)ramcmd->offset & 3) != 0)
{
ret = -EINVAL;
}
else
{
ft80x_write_memory(priv, FT80X_RAM_CMD + ramcmd->offset,
ramcmd->value, ramcmd->nbytes);
ret = OK;
}
}
break;
/* FT80X_IOC_GETREG8:
* Description: Read an 8-bit register value from the FT80x.
* Argument: A reference to an instance of struct
* ft80x_register_s.
* Returns: The 8-bit value read from the register.
*/
case FT80X_IOC_GETREG8:
{
FAR struct ft80x_register_s *reg =
(FAR struct ft80x_register_s *)((uintptr_t)arg);
if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
{
ret = -EINVAL;
}
else
{
reg->value.u8 = ft80x_read_byte(priv, reg->addr);
ret = OK;
}
}
break;
/* FT80X_IOC_GETREG16:
* Description: Read a 16-bit register value from the FT80x.
* Argument: A reference to an instance of struct
* ft80x_register_s.
* Returns: The 16-bit value read from the register.
*/
case FT80X_IOC_GETREG16:
{
FAR struct ft80x_register_s *reg =
(FAR struct ft80x_register_s *)((uintptr_t)arg);
if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
{
ret = -EINVAL;
}
else
{
reg->value.u16 = ft80x_read_hword(priv, reg->addr);
ret = OK;
}
}
break;
/* FT80X_IOC_GETREG32:
* Description: Read a 32-bit register value from the FT80x.
* Argument: A reference to an instance of struct
* ft80x_register_s.
* Returns: The 32-bit value read from the register.
*/
case FT80X_IOC_GETREG32:
{
FAR struct ft80x_register_s *reg =
(FAR struct ft80x_register_s *)((uintptr_t)arg);
if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
{
ret = -EINVAL;
}
else
{
reg->value.u32 = ft80x_read_word(priv, reg->addr);
ret = OK;
}
}
break;
/* FT80X_IOC_GETREGS:
* Description: Read multiple 32-bit register values from the FT80x.
* Argument: A reference to an instance of struct
* ft80x_registers_s.
* Returns: The 32-bit values read from the consecutive
* registers .
*/
case FT80X_IOC_GETREGS:
{
FAR struct ft80x_registers_s *regs =
(FAR struct ft80x_registers_s *)((uintptr_t)arg);
if (regs == NULL || ((uintptr_t)regs->addr & 3) != 0)
{
ret = -EINVAL;
}
else
{
ft80x_read_memory(priv, regs->addr, regs->value,
(size_t)regs->nregs << 2);
ret = OK;
}
}
break;
/* FT80X_IOC_PUTREG8:
* Description: Write an 8-bit register value to the FT80x.
* Argument: A reference to an instance of struct
* ft80x_register_s.
* Returns: None.
*/
case FT80X_IOC_PUTREG8:
{
FAR struct ft80x_register_s *reg =
(FAR struct ft80x_register_s *)((uintptr_t)arg);
if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
{
ret = -EINVAL;
}
else
{
ft80x_write_byte(priv, reg->addr, reg->value.u8);
ret = OK;
}
}
break;
/* FT80X_IOC_PUTREG16:
* Description: Write a 16-bit register value to the FT80x.
* Argument: A reference to an instance of struct
* ft80x_register_s.
* Returns: None.
*/
case FT80X_IOC_PUTREG16:
{
FAR struct ft80x_register_s *reg =
(FAR struct ft80x_register_s *)((uintptr_t)arg);
if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
{
ret = -EINVAL;
}
else
{
ft80x_write_hword(priv, reg->addr, reg->value.u16);
ret = OK;
}
}
break;
/* FT80X_IOC_PUTREG32:
* Description: Write a 32-bit register value to the FT80x.
* Argument: A reference to an instance of struct
* ft80x_register_s.
* Returns: None.
*/
case FT80X_IOC_PUTREG32:
{
FAR struct ft80x_register_s *reg =
(FAR struct ft80x_register_s *)((uintptr_t)arg);
if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
{
ret = -EINVAL;
}
else
{
ft80x_write_word(priv, reg->addr, reg->value.u32);
ret = OK;
}
}
break;
/* FT80X_IOC_PUTREGS:
* Description: Write multiple 32-bit register values to the FT80x.
* Argument: A reference to an instance of struct
* ft80x_registers_s.
* Returns: None.
*/
case FT80X_IOC_PUTREGS:
{
FAR struct ft80x_registers_s *regs =
(FAR struct ft80x_registers_s *)((uintptr_t)arg);
if (regs == NULL || ((uintptr_t)regs->addr & 3) != 0)
{
ret = -EINVAL;
}
else
{
ft80x_write_memory(priv, regs->addr, regs->value,
(size_t)regs->nregs << 2);
ret = OK;
}
}
break;
/* FT80X_IOC_EVENTNOTIFY:
* Description: Setup to receive a signal when an event occurs.
* Argument: A reference to an instance of struct ft80x_notify_s.
* Returns: None
*/
case FT80X_IOC_EVENTNOTIFY:
{
FAR struct ft80x_notify_s *notify =
(FAR struct ft80x_notify_s *)((uintptr_t)arg);
if (notify == NULL || notify->pid < 0 ||
(unsigned int)notify->id >= FT80X_INT_NEVENTS)
{
ret = -EINVAL;
}
else
{
FAR struct ft80x_eventinfo_s *info = &priv->notify[notify->id];
uint32_t regval;
/* Are we enabling or disabling */
if (notify->enable)
{
/* Make sure that arguments are valid for the enable */
if (notify->pid == 0)
{
ret = -EINVAL;
}
else
{
/* Setup the new notification information */
info->event = notify->event;
info->pid = notify->pid;
info->enable = true;
/* Enable interrupts associated with the event */
regval = ft80x_read_word(priv, FT80X_REG_INT_MASK);
regval |= (1 << notify->id);
ft80x_write_word(priv, FT80X_REG_INT_MASK, regval);
ret = OK;
}
}
else
{
/* Disable the notification */
info->pid = 0;
info->enable = false;
/* Disable interrupts associated with the event */
regval = ft80x_read_word(priv, FT80X_REG_INT_MASK);
regval &= ~(1 << notify->id);
ft80x_write_word(priv, FT80X_REG_INT_MASK, regval);
/* Cancel any pending notification */
nxsig_cancel_notification(&info->work);
ret = OK;
}
}
}
break;
/* FT80X_IOC_FADE:
* Description: Change the backlight intensity with a controllable
* fade.
* Argument: A reference to an instance of struct ft80x_fade_s.
* Returns: None.
*/
case FT80X_IOC_FADE:
{
FAR const struct ft80x_fade_s *fade =
(FAR const struct ft80x_fade_s *)((uintptr_t)arg);
if (fade == NULL || fade->duty > 100 ||
fade->delay < MIN_FADE_DELAY || fade->delay > MAX_FADE_DELAY)
{
ret = -EINVAL;
}
else
{
ret = ft80x_fade(priv, fade);
}
}
break;
/* FT80X_IOC_AUDIO:
* Description: Enable/disable an external audio amplifier.
* Argument: 0=disable; 1=enable.
* Returns: None.
*/
case FT80X_IOC_AUDIO:
{
#if defined(CONFIG_LCD_FT80X_AUDIO_MCUSHUTDOWN)
/* Amplifier is controlled by an MCU GPIO pin */
DEBUGASSERT(priv->lower->attach != NULL &&
priv->lower->audio != NULL);
DEBUGASSERT(arg == 0 || arg == 1);
priv->lower->audio(priv->lower, (arg != 0));
ret = OK;
#elif defined(CONFIG_LCD_FT80X_AUDIO_GPIOSHUTDOWN)
/* Amplifier is controlled by an FT80x GPIO pin */
uint8_t regval8;
DEBUGASSERT(arg == 0 || arg == 1);
regval8 = ft80x_read_byte(priv, FT80X_REG_GPIO);
/* Active low logic assumed */
if (arg == 0)
{
regval8 |= (1 << CONFIG_LCD_FT80X_AUDIO_GPIO);
}
else
{
regval8 &= ~(1 << CONFIG_LCD_FT80X_AUDIO_GPIO);
}
ft80x_write_byte(priv, FT80X_REG_GPIO, regval8);
ret = OK;
#else
/* Amplifier is not controllable. */
DEBUGASSERT(arg == 0 || arg == 1);
return OK;
#endif
}
break;
/* Unrecognized IOCTL command */
default:
lcderr("ERROR: Unrecognized cmd: %d arg: %ld\n", cmd, arg);
ret = -ENOTTY;
break;
}
nxmutex_unlock(&priv->lock);
return ret;
}