Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/mfd/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  wl1273-core.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * MFD driver for wl1273 FM radio and audio codec submodules.
 *
 * Copyright (C) 2011 Nokia Corporation
 * Author: Matti Aaltonen <matti.j.aaltonen@nokia.com>
 */


#include <linux/mfd/wl1273-core.h>
#include <linux/slab.h>
#include <linux/module.h>

#define DRIVER_DESC "WL1273 FM Radio Core"

static const struct i2c_device_id wl1273_driver_id_table[] = {
 { WL1273_FM_DRIVER_NAME },
 { }
};
MODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table);

static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value)
{
 struct i2c_client *client = core->client;
 u8 b[2];
 int r;

 r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b);
 if (r != 2) {
  dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg);
  return -EREMOTEIO;
 }

 *value = (u16)b[0] << 8 | b[1];

 return 0;
}

static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param)
{
 struct i2c_client *client = core->client;
 u8 buf[] = { (param >> 8) & 0xff, param & 0xff };
 int r;

 r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf);
 if (r) {
  dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd);
  return r;
 }

 return 0;
}

static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len)
{
 struct i2c_client *client = core->client;
 struct i2c_msg msg;
 int r;

 msg.addr = client->addr;
 msg.flags = 0;
 msg.buf = data;
 msg.len = len;

 r = i2c_transfer(client->adapter, &msg, 1);
 if (r != 1) {
  dev_err(&client->dev, "%s: write error.\n", __func__);
  return -EREMOTEIO;
 }

 return 0;
}

/**
 * wl1273_fm_set_audio() - Set audio mode.
 * @core: A pointer to the device struct.
 * @new_mode: The new audio mode.
 *
 * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG.
 */

static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode)
{
 int r = 0;

 if (core->mode == WL1273_MODE_OFF ||
     core->mode == WL1273_MODE_SUSPENDED)
  return -EPERM;

 if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) {
  r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET,
     WL1273_PCM_DEF_MODE);
  if (r)
   goto out;

  r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
     core->i2s_mode);
  if (r)
   goto out;

  r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
     WL1273_AUDIO_ENABLE_I2S);
  if (r)
   goto out;

 } else if (core->mode == WL1273_MODE_RX &&
     new_mode == WL1273_AUDIO_ANALOG) {
  r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
     WL1273_AUDIO_ENABLE_ANALOG);
  if (r)
   goto out;

 } else if (core->mode == WL1273_MODE_TX &&
     new_mode == WL1273_AUDIO_DIGITAL) {
  r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
     core->i2s_mode);
  if (r)
   goto out;

  r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
     WL1273_AUDIO_IO_SET_I2S);
  if (r)
   goto out;

 } else if (core->mode == WL1273_MODE_TX &&
     new_mode == WL1273_AUDIO_ANALOG) {
  r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
     WL1273_AUDIO_IO_SET_ANALOG);
  if (r)
   goto out;
 }

 core->audio_mode = new_mode;
out:
 return r;
}

/**
 * wl1273_fm_set_volume() - Set volume.
 * @core: A pointer to the device struct.
 * @volume: The new volume value.
 */

static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
{
 int r;

 if (volume > WL1273_MAX_VOLUME)
  return -EINVAL;

 if (core->volume == volume)
  return 0;

 r = wl1273_fm_write_cmd(core, WL1273_VOLUME_SET, volume);
 if (r)
  return r;

 core->volume = volume;
 return 0;
}

static int wl1273_core_probe(struct i2c_client *client)
{
 struct wl1273_fm_platform_data *pdata = dev_get_platdata(&client->dev);
 struct wl1273_core *core;
 struct mfd_cell *cell;
 int children = 0;
 int r = 0;

 dev_dbg(&client->dev, "%s\n", __func__);

 if (!pdata) {
  dev_err(&client->dev, "No platform data.\n");
  return -EINVAL;
 }

 if (!(pdata->children & WL1273_RADIO_CHILD)) {
  dev_err(&client->dev, "Cannot function without radio child.\n");
  return -EINVAL;
 }

 core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
 if (!core)
  return -ENOMEM;

 core->pdata = pdata;
 core->client = client;
 mutex_init(&core->lock);

 i2c_set_clientdata(client, core);

 dev_dbg(&client->dev, "%s: Have V4L2.\n", __func__);

 cell = &core->cells[children];
 cell->name = "wl1273_fm_radio";
 cell->platform_data = &core;
 cell->pdata_size = sizeof(core);
 children++;

 core->read = wl1273_fm_read_reg;
 core->write = wl1273_fm_write_cmd;
 core->write_data = wl1273_fm_write_data;
 core->set_audio = wl1273_fm_set_audio;
 core->set_volume = wl1273_fm_set_volume;

 if (pdata->children & WL1273_CODEC_CHILD) {
  cell = &core->cells[children];

  dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
  cell->name = "wl1273-codec";
  cell->platform_data = &core;
  cell->pdata_size = sizeof(core);
  children++;
 }

 dev_dbg(&client->dev, "%s: number of children: %d.\n",
  __func__, children);

 r = devm_mfd_add_devices(&client->dev, -1, core->cells,
     children, NULL, 0, NULL);
 if (r)
  goto err;

 return 0;

err:
 pdata->free_resources();

 dev_dbg(&client->dev, "%s\n", __func__);

 return r;
}

static struct i2c_driver wl1273_core_driver = {
 .driver = {
  .name = WL1273_FM_DRIVER_NAME,
 },
 .probe = wl1273_core_probe,
 .id_table = wl1273_driver_id_table,
};

static int __init wl1273_core_init(void)
{
 int r;

 r = i2c_add_driver(&wl1273_core_driver);
 if (r) {
  pr_err(WL1273_FM_DRIVER_NAME
         ": driver registration failed\n");
  return r;
 }

 return r;
}

static void __exit wl1273_core_exit(void)
{
 i2c_del_driver(&wl1273_core_driver);
}
late_initcall(wl1273_core_init);
module_exit(wl1273_core_exit);

MODULE_AUTHOR("Matti Aaltonen ");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

Messung V0.5
C=96 H=90 G=93

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.