linux/sound/soc/codecs/rl6347a.c
<<
>>
Prefs
   1/*
   2 * rl6347a.c - RL6347A class device shared support
   3 *
   4 * Copyright 2015 Realtek Semiconductor Corp.
   5 *
   6 * Author: Oder Chiou <oder_chiou@realtek.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/i2c.h>
  15#include <linux/regmap.h>
  16
  17#include "rl6347a.h"
  18
  19int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value)
  20{
  21        struct i2c_client *client = context;
  22        struct rl6347a_priv *rl6347a = i2c_get_clientdata(client);
  23        u8 data[4];
  24        int ret, i;
  25
  26        /* handle index registers */
  27        if (reg <= 0xff) {
  28                rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
  29                for (i = 0; i < rl6347a->index_cache_size; i++) {
  30                        if (reg == rl6347a->index_cache[i].reg) {
  31                                rl6347a->index_cache[i].def = value;
  32                                break;
  33                        }
  34
  35                }
  36                reg = RL6347A_PROC_COEF;
  37        }
  38
  39        data[0] = (reg >> 24) & 0xff;
  40        data[1] = (reg >> 16) & 0xff;
  41        /*
  42         * 4 bit VID: reg should be 0
  43         * 12 bit VID: value should be 0
  44         * So we use an OR operator to handle it rather than use if condition.
  45         */
  46        data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
  47        data[3] = value & 0xff;
  48
  49        ret = i2c_master_send(client, data, 4);
  50
  51        if (ret == 4)
  52                return 0;
  53        else
  54                dev_err(&client->dev, "I2C error %d\n", ret);
  55        if (ret < 0)
  56                return ret;
  57        else
  58                return -EIO;
  59}
  60EXPORT_SYMBOL_GPL(rl6347a_hw_write);
  61
  62int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value)
  63{
  64        struct i2c_client *client = context;
  65        struct i2c_msg xfer[2];
  66        int ret;
  67        __be32 be_reg;
  68        unsigned int index, vid, buf = 0x0;
  69
  70        /* handle index registers */
  71        if (reg <= 0xff) {
  72                rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
  73                reg = RL6347A_PROC_COEF;
  74        }
  75
  76        reg = reg | 0x80000;
  77        vid = (reg >> 8) & 0xfff;
  78
  79        if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
  80                index = (reg >> 8) & 0xf;
  81                reg = (reg & ~0xf0f) | index;
  82        }
  83        be_reg = cpu_to_be32(reg);
  84
  85        /* Write register */
  86        xfer[0].addr = client->addr;
  87        xfer[0].flags = 0;
  88        xfer[0].len = 4;
  89        xfer[0].buf = (u8 *)&be_reg;
  90
  91        /* Read data */
  92        xfer[1].addr = client->addr;
  93        xfer[1].flags = I2C_M_RD;
  94        xfer[1].len = 4;
  95        xfer[1].buf = (u8 *)&buf;
  96
  97        ret = i2c_transfer(client->adapter, xfer, 2);
  98        if (ret < 0)
  99                return ret;
 100        else if (ret != 2)
 101                return -EIO;
 102
 103        *value = be32_to_cpu(buf);
 104
 105        return 0;
 106}
 107EXPORT_SYMBOL_GPL(rl6347a_hw_read);
 108
 109MODULE_DESCRIPTION("RL6347A class device shared support");
 110MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
 111MODULE_LICENSE("GPL v2");
 112