mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 22:51:42 +00:00
Merge remote-tracking branches 'asoc/topic/rcar', 'asoc/topic/reg-default', 'asoc/topic/rl6231', 'asoc/topic/rockchip' and 'asoc/topic/rt286' into asoc-next
This commit is contained in:
commit
532161e6cc
@ -18,6 +18,12 @@ Required properties:
|
||||
- rcar_sound,src : Should contain SRC feature.
|
||||
The number of SRC subnode should be same as HW.
|
||||
see below for detail.
|
||||
- rcar_sound,ctu : Should contain CTU feature.
|
||||
The number of CTU subnode should be same as HW.
|
||||
see below for detail.
|
||||
- rcar_sound,mix : Should contain MIX feature.
|
||||
The number of MIX subnode should be same as HW.
|
||||
see below for detail.
|
||||
- rcar_sound,dvc : Should contain DVC feature.
|
||||
The number of DVC subnode should be same as HW.
|
||||
see below for detail.
|
||||
@ -90,6 +96,22 @@ rcar_sound: sound@ec500000 {
|
||||
};
|
||||
};
|
||||
|
||||
rcar_sound,mix {
|
||||
mix0: mix@0 { };
|
||||
mix1: mix@1 { };
|
||||
};
|
||||
|
||||
rcar_sound,ctu {
|
||||
ctu00: ctu@0 { };
|
||||
ctu01: ctu@1 { };
|
||||
ctu02: ctu@2 { };
|
||||
ctu03: ctu@3 { };
|
||||
ctu10: ctu@4 { };
|
||||
ctu11: ctu@5 { };
|
||||
ctu12: ctu@6 { };
|
||||
ctu13: ctu@7 { };
|
||||
};
|
||||
|
||||
rcar_sound,src {
|
||||
src0: src@0 {
|
||||
interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -6,6 +6,7 @@ Required properties:
|
||||
|
||||
- compatible : "renesas,rsrc-card,<board>"
|
||||
Examples with soctypes are:
|
||||
- "renesas,rsrc-card"
|
||||
- "renesas,rsrc-card,lager"
|
||||
- "renesas,rsrc-card,koelsch"
|
||||
Optional properties:
|
||||
@ -29,6 +30,12 @@ Optional subnode properties:
|
||||
- frame-inversion : bool property. Add this if the
|
||||
dai-link uses frame clock inversion.
|
||||
- convert-rate : platform specified sampling rate convert
|
||||
- audio-prefix : see audio-routing
|
||||
- audio-routing : A list of the connections between audio components.
|
||||
Each entry is a pair of strings, the first being the connection's sink,
|
||||
the second being the connection's source. Valid names for sources.
|
||||
use audio-prefix if some components is using same sink/sources naming.
|
||||
it can be used if compatible was "renesas,rsrc-card";
|
||||
|
||||
Required CPU/CODEC subnodes properties:
|
||||
|
||||
|
@ -136,7 +136,7 @@ struct regmap {
|
||||
/* if set, the HW registers are known to match map->reg_defaults */
|
||||
bool no_sync_defaults;
|
||||
|
||||
struct reg_default *patch;
|
||||
struct reg_sequence *patch;
|
||||
int patch_regs;
|
||||
|
||||
/* if set, converts bulk rw to single rw */
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val,
|
||||
bool *change);
|
||||
bool *change, bool force_write);
|
||||
|
||||
static int _regmap_bus_reg_read(void *context, unsigned int reg,
|
||||
unsigned int *val);
|
||||
@ -1178,7 +1178,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
|
||||
ret = _regmap_update_bits(map, range->selector_reg,
|
||||
range->selector_mask,
|
||||
win_page << range->selector_shift,
|
||||
&page_chg);
|
||||
&page_chg, false);
|
||||
|
||||
map->work_buf = orig_work_buf;
|
||||
|
||||
@ -1624,6 +1624,18 @@ int regmap_fields_write(struct regmap_field *field, unsigned int id,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_fields_write);
|
||||
|
||||
int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
|
||||
unsigned int val)
|
||||
{
|
||||
if (id >= field->id_size)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_write_bits(field->regmap,
|
||||
field->reg + (field->id_offset * id),
|
||||
field->mask, val << field->shift);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_fields_force_write);
|
||||
|
||||
/**
|
||||
* regmap_fields_update_bits(): Perform a read/modify/write cycle
|
||||
* on the register field
|
||||
@ -1743,7 +1755,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write);
|
||||
* relative. The page register has been written if that was neccessary.
|
||||
*/
|
||||
static int _regmap_raw_multi_reg_write(struct regmap *map,
|
||||
const struct reg_default *regs,
|
||||
const struct reg_sequence *regs,
|
||||
size_t num_regs)
|
||||
{
|
||||
int ret;
|
||||
@ -1800,12 +1812,12 @@ static unsigned int _regmap_register_page(struct regmap *map,
|
||||
}
|
||||
|
||||
static int _regmap_range_multi_paged_reg_write(struct regmap *map,
|
||||
struct reg_default *regs,
|
||||
struct reg_sequence *regs,
|
||||
size_t num_regs)
|
||||
{
|
||||
int ret;
|
||||
int i, n;
|
||||
struct reg_default *base;
|
||||
struct reg_sequence *base;
|
||||
unsigned int this_page = 0;
|
||||
/*
|
||||
* the set of registers are not neccessarily in order, but
|
||||
@ -1843,7 +1855,7 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map,
|
||||
}
|
||||
|
||||
static int _regmap_multi_reg_write(struct regmap *map,
|
||||
const struct reg_default *regs,
|
||||
const struct reg_sequence *regs,
|
||||
size_t num_regs)
|
||||
{
|
||||
int i;
|
||||
@ -1895,8 +1907,8 @@ static int _regmap_multi_reg_write(struct regmap *map,
|
||||
struct regmap_range_node *range;
|
||||
range = _regmap_range_lookup(map, reg);
|
||||
if (range) {
|
||||
size_t len = sizeof(struct reg_default)*num_regs;
|
||||
struct reg_default *base = kmemdup(regs, len,
|
||||
size_t len = sizeof(struct reg_sequence)*num_regs;
|
||||
struct reg_sequence *base = kmemdup(regs, len,
|
||||
GFP_KERNEL);
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
@ -1929,7 +1941,7 @@ static int _regmap_multi_reg_write(struct regmap *map,
|
||||
* A value of zero will be returned on success, a negative errno will be
|
||||
* returned in error cases.
|
||||
*/
|
||||
int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs,
|
||||
int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs,
|
||||
int num_regs)
|
||||
{
|
||||
int ret;
|
||||
@ -1962,7 +1974,7 @@ EXPORT_SYMBOL_GPL(regmap_multi_reg_write);
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_multi_reg_write_bypassed(struct regmap *map,
|
||||
const struct reg_default *regs,
|
||||
const struct reg_sequence *regs,
|
||||
int num_regs)
|
||||
{
|
||||
int ret;
|
||||
@ -2327,7 +2339,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_read);
|
||||
|
||||
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val,
|
||||
bool *change)
|
||||
bool *change, bool force_write)
|
||||
{
|
||||
int ret;
|
||||
unsigned int tmp, orig;
|
||||
@ -2339,7 +2351,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||
tmp = orig & ~mask;
|
||||
tmp |= val & mask;
|
||||
|
||||
if (tmp != orig) {
|
||||
if (force_write || (tmp != orig)) {
|
||||
ret = _regmap_write(map, reg, tmp);
|
||||
if (change)
|
||||
*change = true;
|
||||
@ -2367,13 +2379,36 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||
int ret;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
ret = _regmap_update_bits(map, reg, mask, val, NULL);
|
||||
ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
|
||||
map->unlock(map->lock_arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_update_bits);
|
||||
|
||||
/**
|
||||
* regmap_write_bits: Perform a read/modify/write cycle on the register map
|
||||
*
|
||||
* @map: Register map to update
|
||||
* @reg: Register to update
|
||||
* @mask: Bitmask to change
|
||||
* @val: New value for bitmask
|
||||
*
|
||||
* Returns zero for success, a negative number on error.
|
||||
*/
|
||||
int regmap_write_bits(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
ret = _regmap_update_bits(map, reg, mask, val, NULL, true);
|
||||
map->unlock(map->lock_arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_write_bits);
|
||||
|
||||
/**
|
||||
* regmap_update_bits_async: Perform a read/modify/write cycle on the register
|
||||
* map asynchronously
|
||||
@ -2398,7 +2433,7 @@ int regmap_update_bits_async(struct regmap *map, unsigned int reg,
|
||||
|
||||
map->async = true;
|
||||
|
||||
ret = _regmap_update_bits(map, reg, mask, val, NULL);
|
||||
ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
|
||||
|
||||
map->async = false;
|
||||
|
||||
@ -2427,7 +2462,7 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
|
||||
int ret;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
ret = _regmap_update_bits(map, reg, mask, val, change);
|
||||
ret = _regmap_update_bits(map, reg, mask, val, change, false);
|
||||
map->unlock(map->lock_arg);
|
||||
return ret;
|
||||
}
|
||||
@ -2460,7 +2495,7 @@ int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
|
||||
|
||||
map->async = true;
|
||||
|
||||
ret = _regmap_update_bits(map, reg, mask, val, change);
|
||||
ret = _regmap_update_bits(map, reg, mask, val, change, false);
|
||||
|
||||
map->async = false;
|
||||
|
||||
@ -2552,10 +2587,10 @@ EXPORT_SYMBOL_GPL(regmap_async_complete);
|
||||
* The caller must ensure that this function cannot be called
|
||||
* concurrently with either itself or regcache_sync().
|
||||
*/
|
||||
int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
||||
int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs,
|
||||
int num_regs)
|
||||
{
|
||||
struct reg_default *p;
|
||||
struct reg_sequence *p;
|
||||
int ret;
|
||||
bool bypass;
|
||||
|
||||
@ -2564,7 +2599,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
||||
return 0;
|
||||
|
||||
p = krealloc(map->patch,
|
||||
sizeof(struct reg_default) * (map->patch_regs + num_regs),
|
||||
sizeof(struct reg_sequence) * (map->patch_regs + num_regs),
|
||||
GFP_KERNEL);
|
||||
if (p) {
|
||||
memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs));
|
||||
|
@ -54,7 +54,7 @@ static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder)
|
||||
}
|
||||
|
||||
/* ADI recommended values for proper operation. */
|
||||
static const struct reg_default adv7511_fixed_registers[] = {
|
||||
static const struct reg_sequence adv7511_fixed_registers[] = {
|
||||
{ 0x98, 0x03 },
|
||||
{ 0x9a, 0xe0 },
|
||||
{ 0x9c, 0x30 },
|
||||
|
@ -313,14 +313,14 @@ static void drv260x_close(struct input_dev *input)
|
||||
gpiod_set_value(haptics->enable_gpio, 0);
|
||||
}
|
||||
|
||||
static const struct reg_default drv260x_lra_cal_regs[] = {
|
||||
static const struct reg_sequence drv260x_lra_cal_regs[] = {
|
||||
{ DRV260X_MODE, DRV260X_AUTO_CAL },
|
||||
{ DRV260X_CTRL3, DRV260X_NG_THRESH_2 },
|
||||
{ DRV260X_FEEDBACK_CTRL, DRV260X_FB_REG_LRA_MODE |
|
||||
DRV260X_BRAKE_FACTOR_4X | DRV260X_LOOP_GAIN_HIGH },
|
||||
};
|
||||
|
||||
static const struct reg_default drv260x_lra_init_regs[] = {
|
||||
static const struct reg_sequence drv260x_lra_init_regs[] = {
|
||||
{ DRV260X_MODE, DRV260X_RT_PLAYBACK },
|
||||
{ DRV260X_A_TO_V_CTRL, DRV260X_AUDIO_HAPTICS_PEAK_20MS |
|
||||
DRV260X_AUDIO_HAPTICS_FILTER_125HZ },
|
||||
@ -337,7 +337,7 @@ static const struct reg_default drv260x_lra_init_regs[] = {
|
||||
{ DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS },
|
||||
};
|
||||
|
||||
static const struct reg_default drv260x_erm_cal_regs[] = {
|
||||
static const struct reg_sequence drv260x_erm_cal_regs[] = {
|
||||
{ DRV260X_MODE, DRV260X_AUTO_CAL },
|
||||
{ DRV260X_A_TO_V_MIN_INPUT, DRV260X_AUDIO_HAPTICS_MIN_IN_VOLT },
|
||||
{ DRV260X_A_TO_V_MAX_INPUT, DRV260X_AUDIO_HAPTICS_MAX_IN_VOLT },
|
||||
|
@ -132,7 +132,7 @@ static void drv2665_close(struct input_dev *input)
|
||||
"Failed to enter standby mode: %d\n", error);
|
||||
}
|
||||
|
||||
static const struct reg_default drv2665_init_regs[] = {
|
||||
static const struct reg_sequence drv2665_init_regs[] = {
|
||||
{ DRV2665_CTRL_2, 0 | DRV2665_10_MS_IDLE_TOUT },
|
||||
{ DRV2665_CTRL_1, DRV2665_25_VPP_GAIN },
|
||||
};
|
||||
|
@ -262,14 +262,14 @@ static void drv2667_close(struct input_dev *input)
|
||||
"Failed to enter standby mode: %d\n", error);
|
||||
}
|
||||
|
||||
static const struct reg_default drv2667_init_regs[] = {
|
||||
static const struct reg_sequence drv2667_init_regs[] = {
|
||||
{ DRV2667_CTRL_2, 0 },
|
||||
{ DRV2667_CTRL_1, DRV2667_25_VPP_GAIN },
|
||||
{ DRV2667_WV_SEQ_0, 1 },
|
||||
{ DRV2667_WV_SEQ_1, 0 }
|
||||
};
|
||||
|
||||
static const struct reg_default drv2667_page1_init[] = {
|
||||
static const struct reg_sequence drv2667_page1_init[] = {
|
||||
{ DRV2667_RAM_HDR_SZ, 0x05 },
|
||||
{ DRV2667_RAM_START_HI, 0x80 },
|
||||
{ DRV2667_RAM_START_LO, 0x06 },
|
||||
|
@ -392,7 +392,7 @@ err:
|
||||
* Register patch to some of the CODECs internal write sequences
|
||||
* to ensure a clean exit from the low power sleep state.
|
||||
*/
|
||||
static const struct reg_default wm5110_sleep_patch[] = {
|
||||
static const struct reg_sequence wm5110_sleep_patch[] = {
|
||||
{ 0x337A, 0xC100 },
|
||||
{ 0x337B, 0x0041 },
|
||||
{ 0x3300, 0xA210 },
|
||||
|
@ -86,7 +86,7 @@ static const struct reg_default twl6040_defaults[] = {
|
||||
{ 0x2E, 0x00 }, /* REG_STATUS (ro) */
|
||||
};
|
||||
|
||||
static struct reg_default twl6040_patch[] = {
|
||||
static struct reg_sequence twl6040_patch[] = {
|
||||
/*
|
||||
* Select I2C bus access to dual access registers
|
||||
* Interrupt register is cleared on read
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define WM5102_NUM_AOD_ISR 2
|
||||
#define WM5102_NUM_ISR 5
|
||||
|
||||
static const struct reg_default wm5102_reva_patch[] = {
|
||||
static const struct reg_sequence wm5102_reva_patch[] = {
|
||||
{ 0x80, 0x0003 },
|
||||
{ 0x221, 0x0090 },
|
||||
{ 0x211, 0x0014 },
|
||||
@ -57,7 +57,7 @@ static const struct reg_default wm5102_reva_patch[] = {
|
||||
{ 0x80, 0x0000 },
|
||||
};
|
||||
|
||||
static const struct reg_default wm5102_revb_patch[] = {
|
||||
static const struct reg_sequence wm5102_revb_patch[] = {
|
||||
{ 0x19, 0x0001 },
|
||||
{ 0x80, 0x0003 },
|
||||
{ 0x081, 0xE022 },
|
||||
@ -80,7 +80,7 @@ static const struct reg_default wm5102_revb_patch[] = {
|
||||
/* We use a function so we can use ARRAY_SIZE() */
|
||||
int wm5102_patch(struct arizona *arizona)
|
||||
{
|
||||
const struct reg_default *wm5102_patch;
|
||||
const struct reg_sequence *wm5102_patch;
|
||||
int patch_size;
|
||||
|
||||
switch (arizona->rev) {
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define WM5110_NUM_AOD_ISR 2
|
||||
#define WM5110_NUM_ISR 5
|
||||
|
||||
static const struct reg_default wm5110_reva_patch[] = {
|
||||
static const struct reg_sequence wm5110_reva_patch[] = {
|
||||
{ 0x80, 0x3 },
|
||||
{ 0x44, 0x20 },
|
||||
{ 0x45, 0x40 },
|
||||
@ -134,7 +134,7 @@ static const struct reg_default wm5110_reva_patch[] = {
|
||||
{ 0x209, 0x002A },
|
||||
};
|
||||
|
||||
static const struct reg_default wm5110_revb_patch[] = {
|
||||
static const struct reg_sequence wm5110_revb_patch[] = {
|
||||
{ 0x80, 0x3 },
|
||||
{ 0x36e, 0x0210 },
|
||||
{ 0x370, 0x0210 },
|
||||
@ -224,7 +224,7 @@ static const struct reg_default wm5110_revb_patch[] = {
|
||||
{ 0x80, 0x0 },
|
||||
};
|
||||
|
||||
static const struct reg_default wm5110_revd_patch[] = {
|
||||
static const struct reg_sequence wm5110_revd_patch[] = {
|
||||
{ 0x80, 0x3 },
|
||||
{ 0x80, 0x3 },
|
||||
{ 0x393, 0x27 },
|
||||
|
@ -243,21 +243,21 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct reg_default wm8994_revc_patch[] = {
|
||||
static const struct reg_sequence wm8994_revc_patch[] = {
|
||||
{ 0x102, 0x3 },
|
||||
{ 0x56, 0x3 },
|
||||
{ 0x817, 0x0 },
|
||||
{ 0x102, 0x0 },
|
||||
};
|
||||
|
||||
static const struct reg_default wm8958_reva_patch[] = {
|
||||
static const struct reg_sequence wm8958_reva_patch[] = {
|
||||
{ 0x102, 0x3 },
|
||||
{ 0xcb, 0x81 },
|
||||
{ 0x817, 0x0 },
|
||||
{ 0x102, 0x0 },
|
||||
};
|
||||
|
||||
static const struct reg_default wm1811_reva_patch[] = {
|
||||
static const struct reg_sequence wm1811_reva_patch[] = {
|
||||
{ 0x102, 0x3 },
|
||||
{ 0x56, 0xc07 },
|
||||
{ 0x5d, 0x7e },
|
||||
@ -326,7 +326,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
||||
{
|
||||
struct wm8994_pdata *pdata;
|
||||
struct regmap_config *regmap_config;
|
||||
const struct reg_default *regmap_patch = NULL;
|
||||
const struct reg_sequence *regmap_patch = NULL;
|
||||
const char *devname;
|
||||
int ret, i, patch_regs = 0;
|
||||
int pulls = 0;
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "arizona.h"
|
||||
|
||||
static const struct reg_default wm8997_reva_patch[] = {
|
||||
static const struct reg_sequence wm8997_reva_patch[] = {
|
||||
{ 0x80, 0x0003 },
|
||||
{ 0x214, 0x0008 },
|
||||
{ 0x458, 0x0000 },
|
||||
|
@ -50,6 +50,17 @@ struct reg_default {
|
||||
unsigned int def;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register/value pairs for sequences of writes
|
||||
*
|
||||
* @reg: Register address.
|
||||
* @def: Register value.
|
||||
*/
|
||||
struct reg_sequence {
|
||||
unsigned int reg;
|
||||
unsigned int def;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_REGMAP
|
||||
|
||||
enum regmap_endian {
|
||||
@ -410,10 +421,10 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
|
||||
const void *val, size_t val_len);
|
||||
int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
|
||||
size_t val_count);
|
||||
int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs,
|
||||
int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs,
|
||||
int num_regs);
|
||||
int regmap_multi_reg_write_bypassed(struct regmap *map,
|
||||
const struct reg_default *regs,
|
||||
const struct reg_sequence *regs,
|
||||
int num_regs);
|
||||
int regmap_raw_write_async(struct regmap *map, unsigned int reg,
|
||||
const void *val, size_t val_len);
|
||||
@ -424,6 +435,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
|
||||
size_t val_count);
|
||||
int regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
int regmap_write_bits(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
int regmap_update_bits_async(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
int regmap_update_bits_check(struct regmap *map, unsigned int reg,
|
||||
@ -450,7 +463,7 @@ void regcache_mark_dirty(struct regmap *map);
|
||||
bool regmap_check_range_table(struct regmap *map, unsigned int reg,
|
||||
const struct regmap_access_table *table);
|
||||
|
||||
int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
||||
int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs,
|
||||
int num_regs);
|
||||
int regmap_parse_val(struct regmap *map, const void *buf,
|
||||
unsigned int *val);
|
||||
@ -503,6 +516,8 @@ int regmap_field_update_bits(struct regmap_field *field,
|
||||
|
||||
int regmap_fields_write(struct regmap_field *field, unsigned int id,
|
||||
unsigned int val);
|
||||
int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
|
||||
unsigned int val);
|
||||
int regmap_fields_read(struct regmap_field *field, unsigned int id,
|
||||
unsigned int *val);
|
||||
int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
|
||||
@ -645,6 +660,13 @@ static inline int regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int regmap_write_bits(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
WARN_ONCE(1, "regmap API is disabled");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int regmap_update_bits_async(struct regmap *map,
|
||||
unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
|
@ -61,6 +61,14 @@ struct rsnd_src_platform_info {
|
||||
/*
|
||||
* flags
|
||||
*/
|
||||
struct rsnd_ctu_platform_info {
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct rsnd_mix_platform_info {
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct rsnd_dvc_platform_info {
|
||||
u32 flags;
|
||||
};
|
||||
@ -68,6 +76,8 @@ struct rsnd_dvc_platform_info {
|
||||
struct rsnd_dai_path_info {
|
||||
struct rsnd_ssi_platform_info *ssi;
|
||||
struct rsnd_src_platform_info *src;
|
||||
struct rsnd_ctu_platform_info *ctu;
|
||||
struct rsnd_mix_platform_info *mix;
|
||||
struct rsnd_dvc_platform_info *dvc;
|
||||
};
|
||||
|
||||
@ -93,6 +103,10 @@ struct rcar_snd_info {
|
||||
int ssi_info_nr;
|
||||
struct rsnd_src_platform_info *src_info;
|
||||
int src_info_nr;
|
||||
struct rsnd_ctu_platform_info *ctu_info;
|
||||
int ctu_info_nr;
|
||||
struct rsnd_mix_platform_info *mix_info;
|
||||
int mix_info_nr;
|
||||
struct rsnd_dvc_platform_info *dvc_info;
|
||||
int dvc_info_nr;
|
||||
struct rsnd_dai_platform_info *dai_info;
|
||||
|
@ -1366,7 +1366,7 @@ static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
|
||||
{
|
||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||
struct arizona *arizona = priv->arizona;
|
||||
struct reg_default dac_comp[] = {
|
||||
struct reg_sequence dac_comp[] = {
|
||||
{ 0x80, 0x3 },
|
||||
{ ARIZONA_DAC_COMP_1, 0 },
|
||||
{ ARIZONA_DAC_COMP_2, 0 },
|
||||
|
@ -241,7 +241,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = {
|
||||
};
|
||||
|
||||
/* Current and threshold powerup sequence Pg37 in datasheet */
|
||||
static const struct reg_default cs35l32_monitor_patch[] = {
|
||||
static const struct reg_sequence cs35l32_monitor_patch[] = {
|
||||
|
||||
{ 0x00, 0x99 },
|
||||
{ 0x48, 0x17 },
|
||||
|
@ -1067,7 +1067,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = {
|
||||
};
|
||||
|
||||
/* Current and threshold powerup sequence Pg37 */
|
||||
static const struct reg_default cs42l52_threshold_patch[] = {
|
||||
static const struct reg_sequence cs42l52_threshold_patch[] = {
|
||||
|
||||
{ 0x00, 0x99 },
|
||||
{ 0x3E, 0xBA },
|
||||
|
@ -1182,7 +1182,7 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
|
||||
static const struct reg_default da7210_regmap_i2c_patch[] = {
|
||||
static const struct reg_sequence da7210_regmap_i2c_patch[] = {
|
||||
|
||||
/* System controller master disable */
|
||||
{ DA7210_STARTUP1, 0x00 },
|
||||
@ -1268,7 +1268,7 @@ static struct i2c_driver da7210_i2c_driver = {
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
|
||||
static const struct reg_default da7210_regmap_spi_patch[] = {
|
||||
static const struct reg_sequence da7210_regmap_spi_patch[] = {
|
||||
/* Dummy read to give two pulses over nCS for SPI */
|
||||
{ DA7210_AUX2, 0x00 },
|
||||
{ DA7210_AUX2, 0x00 },
|
||||
|
@ -11,38 +11,98 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "rl6231.h"
|
||||
|
||||
/**
|
||||
* rl6231_calc_dmic_clk - Calculate the parameter of dmic.
|
||||
* rl6231_get_pre_div - Return the value of pre divider.
|
||||
*
|
||||
* @map: map for setting.
|
||||
* @reg: register.
|
||||
* @sft: shift.
|
||||
*
|
||||
* Return the value of pre divider from given register value.
|
||||
* Return negative error code for unexpected register value.
|
||||
*/
|
||||
int rl6231_get_pre_div(struct regmap *map, unsigned int reg, int sft)
|
||||
{
|
||||
int pd, val;
|
||||
|
||||
regmap_read(map, reg, &val);
|
||||
|
||||
val = (val >> sft) & 0x7;
|
||||
|
||||
switch (val) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
pd = val + 1;
|
||||
break;
|
||||
case 4:
|
||||
pd = 6;
|
||||
break;
|
||||
case 5:
|
||||
pd = 8;
|
||||
break;
|
||||
case 6:
|
||||
pd = 12;
|
||||
break;
|
||||
case 7:
|
||||
pd = 16;
|
||||
break;
|
||||
default:
|
||||
pd = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return pd;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rl6231_get_pre_div);
|
||||
|
||||
/**
|
||||
* rl6231_calc_dmic_clk - Calculate the frequency divider parameter of dmic.
|
||||
*
|
||||
* @rate: base clock rate.
|
||||
*
|
||||
* Choose dmic clock between 1MHz and 3MHz.
|
||||
* It is better for clock to approximate 3MHz.
|
||||
* Choose divider parameter that gives the highest possible DMIC frequency in
|
||||
* 1MHz - 3MHz range.
|
||||
*/
|
||||
int rl6231_calc_dmic_clk(int rate)
|
||||
{
|
||||
int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL;
|
||||
int i, red, bound, temp;
|
||||
int div[] = {2, 3, 4, 6, 8, 12};
|
||||
int i;
|
||||
|
||||
red = 3000000 * 12;
|
||||
for (i = 0; i < ARRAY_SIZE(div); i++) {
|
||||
bound = div[i] * 3000000;
|
||||
if (rate > bound)
|
||||
continue;
|
||||
temp = bound - rate;
|
||||
if (temp < red) {
|
||||
red = temp;
|
||||
idx = i;
|
||||
}
|
||||
if (rate < 1000000 * div[0]) {
|
||||
pr_warn("Base clock rate %d is too low\n", rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return idx;
|
||||
for (i = 0; i < ARRAY_SIZE(div); i++) {
|
||||
/* find divider that gives DMIC frequency below 3MHz */
|
||||
if (3000000 * div[i] >= rate)
|
||||
return i;
|
||||
}
|
||||
|
||||
pr_warn("Base clock rate %d is too high\n", rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rl6231_calc_dmic_clk);
|
||||
|
||||
struct pll_calc_map {
|
||||
unsigned int pll_in;
|
||||
unsigned int pll_out;
|
||||
int k;
|
||||
int n;
|
||||
int m;
|
||||
bool m_bp;
|
||||
};
|
||||
|
||||
static const struct pll_calc_map pll_preset_table[] = {
|
||||
{19200000, 24576000, 3, 30, 3, false},
|
||||
};
|
||||
|
||||
/**
|
||||
* rl6231_pll_calc - Calcualte PLL M/N/K code.
|
||||
* @freq_in: external clock provided to codec.
|
||||
@ -57,7 +117,7 @@ int rl6231_pll_calc(const unsigned int freq_in,
|
||||
const unsigned int freq_out, struct rl6231_pll_code *pll_code)
|
||||
{
|
||||
int max_n = RL6231_PLL_N_MAX, max_m = RL6231_PLL_M_MAX;
|
||||
int k, red, n_t, pll_out, in_t, out_t;
|
||||
int i, k, red, n_t, pll_out, in_t, out_t;
|
||||
int n = 0, m = 0, m_t = 0;
|
||||
int red_t = abs(freq_out - freq_in);
|
||||
bool bypass = false;
|
||||
@ -65,6 +125,18 @@ int rl6231_pll_calc(const unsigned int freq_in,
|
||||
if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pll_preset_table); i++) {
|
||||
if (freq_in == pll_preset_table[i].pll_in &&
|
||||
freq_out == pll_preset_table[i].pll_out) {
|
||||
k = pll_preset_table[i].k;
|
||||
m = pll_preset_table[i].m;
|
||||
n = pll_preset_table[i].n;
|
||||
bypass = pll_preset_table[i].m_bp;
|
||||
pr_debug("Use preset PLL parameter table\n");
|
||||
goto code_find;
|
||||
}
|
||||
}
|
||||
|
||||
k = 100000000 / freq_out - 2;
|
||||
if (k > RL6231_PLL_K_MAX)
|
||||
k = RL6231_PLL_K_MAX;
|
||||
|
@ -30,5 +30,6 @@ int rl6231_calc_dmic_clk(int rate);
|
||||
int rl6231_pll_calc(const unsigned int freq_in,
|
||||
const unsigned int freq_out, struct rl6231_pll_code *pll_code);
|
||||
int rl6231_get_clk_info(int sclk, int rate);
|
||||
int rl6231_get_pre_div(struct regmap *map, unsigned int reg, int sft);
|
||||
|
||||
#endif /* __RL6231_H__ */
|
||||
|
@ -1108,7 +1108,7 @@ static const struct acpi_device_id rt286_acpi_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, rt286_acpi_match);
|
||||
|
||||
static struct dmi_system_id force_combo_jack_table[] = {
|
||||
static const struct dmi_system_id force_combo_jack_table[] = {
|
||||
{
|
||||
.ident = "Intel Wilson Beach",
|
||||
.matches = {
|
||||
@ -1118,7 +1118,7 @@ static struct dmi_system_id force_combo_jack_table[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct dmi_system_id dmi_dell_dino[] = {
|
||||
static const struct dmi_system_id dmi_dell_dino[] = {
|
||||
{
|
||||
.ident = "Dell Dino",
|
||||
.matches = {
|
||||
@ -1157,7 +1157,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
|
||||
}
|
||||
if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) {
|
||||
dev_err(&i2c->dev,
|
||||
"Device with ID register %x is not rt286\n", val);
|
||||
"Device with ID register %#x is not rt286\n", val);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5640_ranges[] = {
|
||||
.window_len = 0x1, },
|
||||
};
|
||||
|
||||
static const struct reg_default init_list[] = {
|
||||
static const struct reg_sequence init_list[] = {
|
||||
{RT5640_PR_BASE + 0x3d, 0x3600},
|
||||
{RT5640_PR_BASE + 0x12, 0x0aa8},
|
||||
{RT5640_PR_BASE + 0x14, 0x0aaa},
|
||||
@ -459,10 +459,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
|
||||
int idx = -EINVAL;
|
||||
|
||||
idx = rl6231_calc_dmic_clk(rt5640->sysclk);
|
||||
int idx, rate;
|
||||
|
||||
rate = rt5640->sysclk / rl6231_get_pre_div(rt5640->regmap,
|
||||
RT5640_ADDA_CLK1, RT5640_I2S_PD1_SFT);
|
||||
idx = rl6231_calc_dmic_clk(rate);
|
||||
if (idx < 0)
|
||||
dev_err(codec->dev, "Failed to set DMIC clock\n");
|
||||
else
|
||||
|
@ -55,7 +55,7 @@ static const struct regmap_range_cfg rt5645_ranges[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct reg_default init_list[] = {
|
||||
static const struct reg_sequence init_list[] = {
|
||||
{RT5645_PR_BASE + 0x3d, 0x3600},
|
||||
{RT5645_PR_BASE + 0x1c, 0xfd20},
|
||||
{RT5645_PR_BASE + 0x20, 0x611f},
|
||||
@ -64,7 +64,7 @@ static const struct reg_default init_list[] = {
|
||||
};
|
||||
#define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
|
||||
|
||||
static const struct reg_default rt5650_init_list[] = {
|
||||
static const struct reg_sequence rt5650_init_list[] = {
|
||||
{0xf6, 0x0100},
|
||||
};
|
||||
|
||||
@ -545,10 +545,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
|
||||
int idx = -EINVAL;
|
||||
|
||||
idx = rl6231_calc_dmic_clk(rt5645->sysclk);
|
||||
int idx, rate;
|
||||
|
||||
rate = rt5645->sysclk / rl6231_get_pre_div(rt5645->regmap,
|
||||
RT5645_ADDA_CLK1, RT5645_I2S_PD1_SFT);
|
||||
idx = rl6231_calc_dmic_clk(rate);
|
||||
if (idx < 0)
|
||||
dev_err(codec->dev, "Failed to set DMIC clock\n");
|
||||
else
|
||||
|
@ -46,7 +46,7 @@ static const struct regmap_range_cfg rt5651_ranges[] = {
|
||||
.window_len = 0x1, },
|
||||
};
|
||||
|
||||
static const struct reg_default init_list[] = {
|
||||
static const struct reg_sequence init_list[] = {
|
||||
{RT5651_PR_BASE + 0x3d, 0x3e00},
|
||||
};
|
||||
|
||||
@ -378,10 +378,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
|
||||
int idx = -EINVAL;
|
||||
|
||||
idx = rl6231_calc_dmic_clk(rt5651->sysclk);
|
||||
int idx, rate;
|
||||
|
||||
rate = rt5651->sysclk / rl6231_get_pre_div(rt5651->regmap,
|
||||
RT5651_ADDA_CLK1, RT5651_I2S_PD1_SFT);
|
||||
idx = rl6231_calc_dmic_clk(rate);
|
||||
if (idx < 0)
|
||||
dev_err(codec->dev, "Failed to set DMIC clock\n");
|
||||
else
|
||||
|
@ -51,7 +51,7 @@ static const struct regmap_range_cfg rt5670_ranges[] = {
|
||||
.window_len = 0x1, },
|
||||
};
|
||||
|
||||
static const struct reg_default init_list[] = {
|
||||
static const struct reg_sequence init_list[] = {
|
||||
{ RT5670_PR_BASE + 0x14, 0x9a8a },
|
||||
{ RT5670_PR_BASE + 0x38, 0x3ba1 },
|
||||
{ RT5670_PR_BASE + 0x3d, 0x3640 },
|
||||
@ -683,10 +683,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
|
||||
int idx = -EINVAL;
|
||||
|
||||
idx = rl6231_calc_dmic_clk(rt5670->sysclk);
|
||||
int idx, rate;
|
||||
|
||||
rate = rt5670->sysclk / rl6231_get_pre_div(rt5670->regmap,
|
||||
RT5670_ADDA_CLK1, RT5670_I2S_PD1_SFT);
|
||||
idx = rl6231_calc_dmic_clk(rate);
|
||||
if (idx < 0)
|
||||
dev_err(codec->dev, "Failed to set DMIC clock\n");
|
||||
else
|
||||
|
@ -54,7 +54,7 @@ static const struct regmap_range_cfg rt5677_ranges[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct reg_default init_list[] = {
|
||||
static const struct reg_sequence init_list[] = {
|
||||
{RT5677_ASRC_12, 0x0018},
|
||||
{RT5677_PR_BASE + 0x3d, 0x364d},
|
||||
{RT5677_PR_BASE + 0x17, 0x4fc0},
|
||||
@ -917,8 +917,11 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
||||
int idx = rl6231_calc_dmic_clk(rt5677->lrck[RT5677_AIF1] << 8);
|
||||
int idx, rate;
|
||||
|
||||
rate = rt5677->sysclk / rl6231_get_pre_div(rt5677->regmap,
|
||||
RT5677_CLK_TREE_CTRL1, RT5677_I2S_PD1_SFT);
|
||||
idx = rl6231_calc_dmic_clk(rate);
|
||||
if (idx < 0)
|
||||
dev_err(codec->dev, "Failed to set DMIC clock\n");
|
||||
else
|
||||
|
@ -1668,7 +1668,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
|
||||
|
||||
static const struct reg_default aic3007_class_d[] = {
|
||||
static const struct reg_sequence aic3007_class_d[] = {
|
||||
/* Class-D speaker driver init; datasheet p. 46 */
|
||||
{ AIC3X_PAGE_SELECT, 0x0D },
|
||||
{ 0xD, 0x0D },
|
||||
|
@ -897,7 +897,7 @@ static bool wm2200_readable_register(struct device *dev, unsigned int reg)
|
||||
}
|
||||
}
|
||||
|
||||
static const struct reg_default wm2200_reva_patch[] = {
|
||||
static const struct reg_sequence wm2200_reva_patch[] = {
|
||||
{ 0x07, 0x0003 },
|
||||
{ 0x102, 0x0200 },
|
||||
{ 0x203, 0x0084 },
|
||||
|
@ -1247,7 +1247,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
|
||||
{ "PWM2", NULL, "PWM2 Driver" },
|
||||
};
|
||||
|
||||
static const struct reg_default wm5100_reva_patches[] = {
|
||||
static const struct reg_sequence wm5100_reva_patches[] = {
|
||||
{ WM5100_AUDIO_IF_1_10, 0 },
|
||||
{ WM5100_AUDIO_IF_1_11, 1 },
|
||||
{ WM5100_AUDIO_IF_1_12, 2 },
|
||||
|
@ -3495,7 +3495,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
|
||||
};
|
||||
|
||||
/* Improve power consumption for IN4 DC measurement mode */
|
||||
static const struct reg_default wm8962_dc_measure[] = {
|
||||
static const struct reg_sequence wm8962_dc_measure[] = {
|
||||
{ 0xfd, 0x1 },
|
||||
{ 0xcc, 0x40 },
|
||||
{ 0xfd, 0 },
|
||||
|
@ -1595,7 +1595,7 @@ static int wm8993_resume(struct snd_soc_codec *codec)
|
||||
#endif
|
||||
|
||||
/* Tune DC servo configuration */
|
||||
static const struct reg_default wm8993_regmap_patch[] = {
|
||||
static const struct reg_sequence wm8993_regmap_patch[] = {
|
||||
{ 0x44, 3 },
|
||||
{ 0x56, 3 },
|
||||
{ 0x44, 0 },
|
||||
|
@ -223,7 +223,6 @@ static struct platform_driver snd_rk_mc_driver = {
|
||||
.probe = snd_rk_mc_probe,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
.of_match_table = rockchip_max98090_of_match,
|
||||
},
|
||||
|
@ -118,7 +118,7 @@ static int rk_init(struct snd_soc_pcm_runtime *runtime)
|
||||
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
||||
SND_JACK_BTN_2 | SND_JACK_BTN_3,
|
||||
&headset_jack, NULL, 0);
|
||||
if (!ret) {
|
||||
if (ret) {
|
||||
dev_err(card->dev, "New Headset Jack failed! (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -212,7 +212,6 @@ static struct platform_driver snd_rk_mc_driver = {
|
||||
.probe = snd_rk_mc_probe,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
.of_match_table = rockchip_rt5645_of_match,
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
snd-soc-rcar-objs := core.o gen.o dma.o src.o adg.o ssi.o dvc.o
|
||||
snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o ctu.o mix.o dvc.o
|
||||
obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
|
||||
|
||||
snd-soc-rsrc-card-objs := rsrc-card.o
|
||||
|
@ -203,9 +203,9 @@ int rsnd_io_is_working(struct rsnd_dai_stream *io)
|
||||
}
|
||||
|
||||
/*
|
||||
* settting function
|
||||
* ADINR function
|
||||
*/
|
||||
u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
|
||||
u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
|
||||
{
|
||||
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
|
||||
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
|
||||
@ -227,6 +227,64 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
|
||||
return adinr;
|
||||
}
|
||||
|
||||
u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
|
||||
{
|
||||
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
|
||||
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
u32 chan = runtime->channels;
|
||||
|
||||
switch (chan) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 8:
|
||||
break;
|
||||
default:
|
||||
dev_warn(dev, "not supported channel\n");
|
||||
chan = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
/*
|
||||
* DALIGN function
|
||||
*/
|
||||
u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
|
||||
{
|
||||
struct rsnd_mod *src = rsnd_io_to_mod_src(io);
|
||||
struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
|
||||
struct rsnd_mod *target = src ? src : ssi;
|
||||
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
|
||||
u32 val = 0x76543210;
|
||||
u32 mask = ~0;
|
||||
|
||||
mask <<= runtime->channels * 4;
|
||||
val = val & mask;
|
||||
|
||||
switch (runtime->sample_bits) {
|
||||
case 16:
|
||||
val |= 0x67452301 & ~mask;
|
||||
break;
|
||||
case 32:
|
||||
val |= 0x76543210 & ~mask;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* exchange channeles on SRC if possible,
|
||||
* otherwise, R/L volume settings on DVC
|
||||
* changes inverted channels
|
||||
*/
|
||||
if (mod == target)
|
||||
return val;
|
||||
else
|
||||
return 0x76543210;
|
||||
}
|
||||
|
||||
/*
|
||||
* rsnd_dai functions
|
||||
*/
|
||||
@ -242,9 +300,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
|
||||
if (val == __rsnd_mod_call_##func) { \
|
||||
called = 1; \
|
||||
ret = (mod)->ops->func(mod, io, param); \
|
||||
mod->status = (mod->status & ~mask) + \
|
||||
(add << __rsnd_mod_shift_##func); \
|
||||
} \
|
||||
mod->status = (mod->status & ~mask) + \
|
||||
(add << __rsnd_mod_shift_##func); \
|
||||
dev_dbg(dev, "%s[%d] 0x%08x %s\n", \
|
||||
rsnd_mod_name(mod), rsnd_mod_id(mod), mod->status, \
|
||||
called ? #func : ""); \
|
||||
@ -274,21 +332,21 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
|
||||
static int rsnd_dai_connect(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io)
|
||||
{
|
||||
struct rsnd_priv *priv;
|
||||
struct device *dev;
|
||||
|
||||
if (!mod)
|
||||
return -EIO;
|
||||
|
||||
if (io->mod[mod->type]) {
|
||||
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
|
||||
dev_err(dev, "%s[%d] is not empty\n",
|
||||
rsnd_mod_name(mod),
|
||||
rsnd_mod_id(mod));
|
||||
return -EIO;
|
||||
}
|
||||
priv = rsnd_mod_to_priv(mod);
|
||||
dev = rsnd_priv_to_dev(priv);
|
||||
|
||||
io->mod[mod->type] = mod;
|
||||
|
||||
dev_dbg(dev, "%s[%d] is connected to io (%s)\n",
|
||||
rsnd_mod_name(mod), rsnd_mod_id(mod),
|
||||
rsnd_io_is_play(io) ? "Playback" : "Capture");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -517,7 +575,7 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
|
||||
.set_fmt = rsnd_soc_dai_set_fmt,
|
||||
};
|
||||
|
||||
#define rsnd_path_parse(priv, io, type) \
|
||||
#define rsnd_path_add(priv, io, type) \
|
||||
({ \
|
||||
struct rsnd_mod *mod; \
|
||||
int ret = 0; \
|
||||
@ -533,7 +591,7 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
|
||||
ret; \
|
||||
})
|
||||
|
||||
#define rsnd_path_break(priv, io, type) \
|
||||
#define rsnd_path_remove(priv, io, type) \
|
||||
{ \
|
||||
struct rsnd_mod *mod; \
|
||||
int id = -1; \
|
||||
@ -547,6 +605,79 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
|
||||
} \
|
||||
}
|
||||
|
||||
void rsnd_path_parse(struct rsnd_priv *priv,
|
||||
struct rsnd_dai_stream *io)
|
||||
{
|
||||
struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
|
||||
struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
|
||||
struct rsnd_mod *src = rsnd_io_to_mod_src(io);
|
||||
struct rsnd_mod *cmd;
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
u32 data;
|
||||
|
||||
/* Gen1 is not supported */
|
||||
if (rsnd_is_gen1(priv))
|
||||
return;
|
||||
|
||||
if (!mix && !dvc)
|
||||
return;
|
||||
|
||||
if (mix) {
|
||||
struct rsnd_dai *rdai;
|
||||
int i;
|
||||
u32 path[] = {
|
||||
[0] = 0,
|
||||
[1] = 1 << 0,
|
||||
[2] = 0,
|
||||
[3] = 0,
|
||||
[4] = 0,
|
||||
[5] = 1 << 8
|
||||
};
|
||||
|
||||
/*
|
||||
* it is assuming that integrater is well understanding about
|
||||
* data path. Here doesn't check impossible connection,
|
||||
* like src2 + src5
|
||||
*/
|
||||
data = 0;
|
||||
for_each_rsnd_dai(rdai, priv, i) {
|
||||
io = &rdai->playback;
|
||||
if (mix == rsnd_io_to_mod_mix(io))
|
||||
data |= path[rsnd_mod_id(src)];
|
||||
|
||||
io = &rdai->capture;
|
||||
if (mix == rsnd_io_to_mod_mix(io))
|
||||
data |= path[rsnd_mod_id(src)];
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't use ctu = rsnd_io_ctu() here.
|
||||
* Since, ID of dvc/mix are 0 or 1 (= same as CMD number)
|
||||
* but ctu IDs are 0 - 7 (= CTU00 - CTU13)
|
||||
*/
|
||||
cmd = mix;
|
||||
} else {
|
||||
u32 path[] = {
|
||||
[0] = 0x30000,
|
||||
[1] = 0x30001,
|
||||
[2] = 0x40000,
|
||||
[3] = 0x10000,
|
||||
[4] = 0x20000,
|
||||
[5] = 0x40100
|
||||
};
|
||||
|
||||
data = path[rsnd_mod_id(src)];
|
||||
|
||||
cmd = dvc;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "ctu/mix path = 0x%08x", data);
|
||||
|
||||
rsnd_mod_write(cmd, CMD_ROUTE_SLCT, data);
|
||||
|
||||
rsnd_mod_write(cmd, CMD_CTRL, 0x10);
|
||||
}
|
||||
|
||||
static int rsnd_path_init(struct rsnd_priv *priv,
|
||||
struct rsnd_dai *rdai,
|
||||
struct rsnd_dai_stream *io)
|
||||
@ -564,18 +695,28 @@ static int rsnd_path_init(struct rsnd_priv *priv,
|
||||
* using fixed path.
|
||||
*/
|
||||
|
||||
/* SRC */
|
||||
ret = rsnd_path_parse(priv, io, src);
|
||||
/* SSI */
|
||||
ret = rsnd_path_add(priv, io, ssi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* SSI */
|
||||
ret = rsnd_path_parse(priv, io, ssi);
|
||||
/* SRC */
|
||||
ret = rsnd_path_add(priv, io, src);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* CTU */
|
||||
ret = rsnd_path_add(priv, io, ctu);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* MIX */
|
||||
ret = rsnd_path_add(priv, io, mix);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* DVC */
|
||||
ret = rsnd_path_parse(priv, io, dvc);
|
||||
ret = rsnd_path_add(priv, io, dvc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -589,13 +730,15 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
|
||||
struct device_node *dai_node, *dai_np;
|
||||
struct device_node *ssi_node, *ssi_np;
|
||||
struct device_node *src_node, *src_np;
|
||||
struct device_node *ctu_node, *ctu_np;
|
||||
struct device_node *mix_node, *mix_np;
|
||||
struct device_node *dvc_node, *dvc_np;
|
||||
struct device_node *playback, *capture;
|
||||
struct rsnd_dai_platform_info *dai_info;
|
||||
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
|
||||
struct device *dev = &pdev->dev;
|
||||
int nr, i;
|
||||
int dai_i, ssi_i, src_i, dvc_i;
|
||||
int dai_i, ssi_i, src_i, ctu_i, mix_i, dvc_i;
|
||||
|
||||
if (!of_data)
|
||||
return;
|
||||
@ -621,6 +764,8 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
|
||||
|
||||
ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
|
||||
src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src");
|
||||
ctu_node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu");
|
||||
mix_node = of_get_child_by_name(dev->of_node, "rcar_sound,mix");
|
||||
dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc");
|
||||
|
||||
#define mod_parse(name) \
|
||||
@ -657,6 +802,8 @@ if (name##_node) { \
|
||||
|
||||
mod_parse(ssi);
|
||||
mod_parse(src);
|
||||
mod_parse(ctu);
|
||||
mod_parse(mix);
|
||||
mod_parse(dvc);
|
||||
|
||||
of_node_put(playback);
|
||||
@ -1033,8 +1180,8 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
|
||||
/*
|
||||
* remove SRC/DVC from DAI,
|
||||
*/
|
||||
rsnd_path_break(priv, io, src);
|
||||
rsnd_path_break(priv, io, dvc);
|
||||
rsnd_path_remove(priv, io, src);
|
||||
rsnd_path_remove(priv, io, dvc);
|
||||
|
||||
/*
|
||||
* fallback
|
||||
@ -1069,6 +1216,8 @@ static int rsnd_probe(struct platform_device *pdev)
|
||||
rsnd_dma_probe,
|
||||
rsnd_ssi_probe,
|
||||
rsnd_src_probe,
|
||||
rsnd_ctu_probe,
|
||||
rsnd_mix_probe,
|
||||
rsnd_dvc_probe,
|
||||
rsnd_adg_probe,
|
||||
rsnd_dai_probe,
|
||||
@ -1164,6 +1313,8 @@ static int rsnd_remove(struct platform_device *pdev)
|
||||
struct rsnd_priv *priv) = {
|
||||
rsnd_ssi_remove,
|
||||
rsnd_src_remove,
|
||||
rsnd_ctu_remove,
|
||||
rsnd_mix_remove,
|
||||
rsnd_dvc_remove,
|
||||
};
|
||||
int ret = 0, i;
|
||||
|
171
sound/soc/sh/rcar/ctu.c
Normal file
171
sound/soc/sh/rcar/ctu.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* ctu.c
|
||||
*
|
||||
* Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include "rsnd.h"
|
||||
|
||||
#define CTU_NAME_SIZE 16
|
||||
#define CTU_NAME "ctu"
|
||||
|
||||
struct rsnd_ctu {
|
||||
struct rsnd_ctu_platform_info *info; /* rcar_snd.h */
|
||||
struct rsnd_mod mod;
|
||||
};
|
||||
|
||||
#define rsnd_ctu_nr(priv) ((priv)->ctu_nr)
|
||||
#define for_each_rsnd_ctu(pos, priv, i) \
|
||||
for ((i) = 0; \
|
||||
((i) < rsnd_ctu_nr(priv)) && \
|
||||
((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \
|
||||
i++)
|
||||
|
||||
#define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1)
|
||||
#define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0)
|
||||
static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable)
|
||||
{
|
||||
rsnd_mod_write(mod, CTU_CTUIR, enable);
|
||||
}
|
||||
|
||||
static int rsnd_ctu_init(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
rsnd_mod_hw_start(mod);
|
||||
|
||||
rsnd_ctu_initialize_lock(mod);
|
||||
|
||||
rsnd_mod_write(mod, CTU_ADINR, rsnd_get_adinr_chan(mod, io));
|
||||
|
||||
rsnd_ctu_initialize_unlock(mod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsnd_ctu_quit(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
rsnd_mod_hw_stop(mod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rsnd_mod_ops rsnd_ctu_ops = {
|
||||
.name = CTU_NAME,
|
||||
.init = rsnd_ctu_init,
|
||||
.quit = rsnd_ctu_quit,
|
||||
};
|
||||
|
||||
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
|
||||
{
|
||||
if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
|
||||
id = 0;
|
||||
|
||||
return &((struct rsnd_ctu *)(priv->ctu) + id)->mod;
|
||||
}
|
||||
|
||||
static void rsnd_of_parse_ctu(struct platform_device *pdev,
|
||||
const struct rsnd_of_data *of_data,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
struct device_node *node;
|
||||
struct rsnd_ctu_platform_info *ctu_info;
|
||||
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
|
||||
struct device *dev = &pdev->dev;
|
||||
int nr;
|
||||
|
||||
if (!of_data)
|
||||
return;
|
||||
|
||||
node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu");
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
nr = of_get_child_count(node);
|
||||
if (!nr)
|
||||
goto rsnd_of_parse_ctu_end;
|
||||
|
||||
ctu_info = devm_kzalloc(dev,
|
||||
sizeof(struct rsnd_ctu_platform_info) * nr,
|
||||
GFP_KERNEL);
|
||||
if (!ctu_info) {
|
||||
dev_err(dev, "ctu info allocation error\n");
|
||||
goto rsnd_of_parse_ctu_end;
|
||||
}
|
||||
|
||||
info->ctu_info = ctu_info;
|
||||
info->ctu_info_nr = nr;
|
||||
|
||||
rsnd_of_parse_ctu_end:
|
||||
of_node_put(node);
|
||||
|
||||
}
|
||||
|
||||
int rsnd_ctu_probe(struct platform_device *pdev,
|
||||
const struct rsnd_of_data *of_data,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
struct rsnd_ctu *ctu;
|
||||
struct clk *clk;
|
||||
char name[CTU_NAME_SIZE];
|
||||
int i, nr, ret;
|
||||
|
||||
/* This driver doesn't support Gen1 at this point */
|
||||
if (rsnd_is_gen1(priv)) {
|
||||
dev_warn(dev, "CTU is not supported on Gen1\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rsnd_of_parse_ctu(pdev, of_data, priv);
|
||||
|
||||
nr = info->ctu_info_nr;
|
||||
if (!nr)
|
||||
return 0;
|
||||
|
||||
ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL);
|
||||
if (!ctu)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->ctu_nr = nr;
|
||||
priv->ctu = ctu;
|
||||
|
||||
for_each_rsnd_ctu(ctu, priv, i) {
|
||||
/*
|
||||
* CTU00, CTU01, CTU02, CTU03 => CTU0
|
||||
* CTU10, CTU11, CTU12, CTU13 => CTU1
|
||||
*/
|
||||
snprintf(name, CTU_NAME_SIZE, "%s.%d",
|
||||
CTU_NAME, i / 4);
|
||||
|
||||
clk = devm_clk_get(dev, name);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
ctu->info = &info->ctu_info[i];
|
||||
|
||||
ret = rsnd_mod_init(priv, &ctu->mod, &rsnd_ctu_ops,
|
||||
clk, RSND_MOD_CTU, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rsnd_ctu_remove(struct platform_device *pdev,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
struct rsnd_ctu *ctu;
|
||||
int i;
|
||||
|
||||
for_each_rsnd_ctu(ctu, priv, i) {
|
||||
rsnd_mod_quit(&ctu->mod);
|
||||
}
|
||||
}
|
@ -27,6 +27,15 @@ struct rsnd_dma_ctrl {
|
||||
int dmapp_num;
|
||||
};
|
||||
|
||||
struct rsnd_dma_ops {
|
||||
char *name;
|
||||
void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
|
||||
void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
|
||||
int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id,
|
||||
struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
|
||||
void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
|
||||
};
|
||||
|
||||
#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma)
|
||||
|
||||
/*
|
||||
@ -168,7 +177,7 @@ static int rsnd_dmaen_init(struct rsnd_dai_stream *io,
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
|
||||
dmaen->chan = dma_request_channel(mask, shdma_chan_filter,
|
||||
(void *)id);
|
||||
(void *)(uintptr_t)id);
|
||||
}
|
||||
if (IS_ERR_OR_NULL(dmaen->chan)) {
|
||||
dmaen->chan = NULL;
|
||||
@ -182,7 +191,8 @@ static int rsnd_dmaen_init(struct rsnd_dai_stream *io,
|
||||
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
|
||||
dev_dbg(dev, "dma : %pad -> %pad\n",
|
||||
dev_dbg(dev, "%s %pad -> %pad\n",
|
||||
dma->ops->name,
|
||||
&cfg.src_addr, &cfg.dst_addr);
|
||||
|
||||
ret = dmaengine_slave_config(dmaen->chan, &cfg);
|
||||
@ -215,6 +225,7 @@ static void rsnd_dmaen_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
|
||||
}
|
||||
|
||||
static struct rsnd_dma_ops rsnd_dmaen_ops = {
|
||||
.name = "audmac",
|
||||
.start = rsnd_dmaen_start,
|
||||
.stop = rsnd_dmaen_stop,
|
||||
.init = rsnd_dmaen_init,
|
||||
@ -360,6 +371,7 @@ static int rsnd_dmapp_init(struct rsnd_dai_stream *io,
|
||||
}
|
||||
|
||||
static struct rsnd_dma_ops rsnd_dmapp_ops = {
|
||||
.name = "audmac-pp",
|
||||
.start = rsnd_dmapp_start,
|
||||
.stop = rsnd_dmapp_stop,
|
||||
.init = rsnd_dmapp_init,
|
||||
@ -414,7 +426,9 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
|
||||
phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU);
|
||||
int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod);
|
||||
int use_src = !!rsnd_io_to_mod_src(io);
|
||||
int use_dvc = !!rsnd_io_to_mod_dvc(io);
|
||||
int use_cmd = !!rsnd_io_to_mod_dvc(io) ||
|
||||
!!rsnd_io_to_mod_mix(io) ||
|
||||
!!rsnd_io_to_mod_ctu(io);
|
||||
int id = rsnd_mod_id(mod);
|
||||
struct dma_addr {
|
||||
dma_addr_t out_addr;
|
||||
@ -452,7 +466,7 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
|
||||
};
|
||||
|
||||
/* it shouldn't happen */
|
||||
if (use_dvc && !use_src)
|
||||
if (use_cmd && !use_src)
|
||||
dev_err(dev, "DVC is selected without SRC\n");
|
||||
|
||||
/* use SSIU or SSI ? */
|
||||
@ -460,8 +474,8 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
|
||||
is_ssi++;
|
||||
|
||||
return (is_from) ?
|
||||
dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr :
|
||||
dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr;
|
||||
dma_addrs[is_ssi][is_play][use_src + use_cmd].out_addr :
|
||||
dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr;
|
||||
}
|
||||
|
||||
static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
|
||||
@ -482,7 +496,7 @@ static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
|
||||
return rsnd_gen2_dma_addr(io, mod, is_play, is_from);
|
||||
}
|
||||
|
||||
#define MOD_MAX 4 /* MEM/SSI/SRC/DVC */
|
||||
#define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */
|
||||
static void rsnd_dma_of_path(struct rsnd_dma *dma,
|
||||
struct rsnd_dai_stream *io,
|
||||
int is_play,
|
||||
@ -492,55 +506,81 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
|
||||
struct rsnd_mod *this = rsnd_dma_to_mod(dma);
|
||||
struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
|
||||
struct rsnd_mod *src = rsnd_io_to_mod_src(io);
|
||||
struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io);
|
||||
struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
|
||||
struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
|
||||
struct rsnd_mod *mod[MOD_MAX];
|
||||
int i, index;
|
||||
struct rsnd_mod *mod_start, *mod_end;
|
||||
struct rsnd_priv *priv = rsnd_mod_to_priv(this);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
int nr, i;
|
||||
|
||||
if (!ssi)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MOD_MAX; i++)
|
||||
nr = 0;
|
||||
for (i = 0; i < MOD_MAX; i++) {
|
||||
mod[i] = NULL;
|
||||
|
||||
/*
|
||||
* in play case...
|
||||
*
|
||||
* src -> dst
|
||||
*
|
||||
* mem -> SSI
|
||||
* mem -> SRC -> SSI
|
||||
* mem -> SRC -> DVC -> SSI
|
||||
*/
|
||||
mod[0] = NULL; /* for "mem" */
|
||||
index = 1;
|
||||
for (i = 1; i < MOD_MAX; i++) {
|
||||
if (!src) {
|
||||
mod[i] = ssi;
|
||||
} else if (!dvc) {
|
||||
mod[i] = src;
|
||||
src = NULL;
|
||||
} else {
|
||||
if ((!is_play) && (this == src))
|
||||
this = dvc;
|
||||
|
||||
mod[i] = (is_play) ? src : dvc;
|
||||
i++;
|
||||
mod[i] = (is_play) ? dvc : src;
|
||||
src = NULL;
|
||||
dvc = NULL;
|
||||
}
|
||||
|
||||
if (mod[i] == this)
|
||||
index = i;
|
||||
|
||||
if (mod[i] == ssi)
|
||||
break;
|
||||
nr += !!rsnd_io_to_mod(io, i);
|
||||
}
|
||||
|
||||
if (is_play) {
|
||||
*mod_from = mod[index - 1];
|
||||
*mod_to = mod[index];
|
||||
/*
|
||||
* [S] -*-> [E]
|
||||
* [S] -*-> SRC -o-> [E]
|
||||
* [S] -*-> SRC -> DVC -o-> [E]
|
||||
* [S] -*-> SRC -> CTU -> MIX -> DVC -o-> [E]
|
||||
*
|
||||
* playback [S] = mem
|
||||
* [E] = SSI
|
||||
*
|
||||
* capture [S] = SSI
|
||||
* [E] = mem
|
||||
*
|
||||
* -*-> Audio DMAC
|
||||
* -o-> Audio DMAC peri peri
|
||||
*/
|
||||
mod_start = (is_play) ? NULL : ssi;
|
||||
mod_end = (is_play) ? ssi : NULL;
|
||||
|
||||
mod[0] = mod_start;
|
||||
for (i = 1; i < nr; i++) {
|
||||
if (src) {
|
||||
mod[i] = src;
|
||||
src = NULL;
|
||||
} else if (ctu) {
|
||||
mod[i] = ctu;
|
||||
ctu = NULL;
|
||||
} else if (mix) {
|
||||
mod[i] = mix;
|
||||
mix = NULL;
|
||||
} else if (dvc) {
|
||||
mod[i] = dvc;
|
||||
dvc = NULL;
|
||||
}
|
||||
}
|
||||
mod[i] = mod_end;
|
||||
|
||||
/*
|
||||
* | SSI | SRC |
|
||||
* -------------+-----+-----+
|
||||
* is_play | o | * |
|
||||
* !is_play | * | o |
|
||||
*/
|
||||
if ((this == ssi) == (is_play)) {
|
||||
*mod_from = mod[nr - 1];
|
||||
*mod_to = mod[nr];
|
||||
} else {
|
||||
*mod_from = mod[index];
|
||||
*mod_to = mod[index - 1];
|
||||
*mod_from = mod[0];
|
||||
*mod_to = mod[1];
|
||||
}
|
||||
|
||||
dev_dbg(dev, "module connection (this is %s[%d])\n",
|
||||
rsnd_mod_name(this), rsnd_mod_id(this));
|
||||
for (i = 0; i <= nr; i++) {
|
||||
dev_dbg(dev, " %s[%d]%s\n",
|
||||
rsnd_mod_name(mod[i]), rsnd_mod_id(mod[i]),
|
||||
(mod[i] == *mod_from) ? " from" :
|
||||
(mod[i] == *mod_to) ? " to" : "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -568,10 +608,11 @@ void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
|
||||
|
||||
int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id)
|
||||
{
|
||||
struct rsnd_mod *mod_from;
|
||||
struct rsnd_mod *mod_to;
|
||||
struct rsnd_mod *mod_from = NULL;
|
||||
struct rsnd_mod *mod_to = NULL;
|
||||
struct rsnd_priv *priv = rsnd_io_to_priv(io);
|
||||
struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
int is_play = rsnd_io_is_play(io);
|
||||
|
||||
/*
|
||||
@ -598,6 +639,11 @@ int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id)
|
||||
if (rsnd_is_gen1(priv))
|
||||
dma->ops = &rsnd_dmaen_ops;
|
||||
|
||||
dev_dbg(dev, "%s %s[%d] -> %s[%d]\n",
|
||||
dma->ops->name,
|
||||
rsnd_mod_name(mod_from), rsnd_mod_id(mod_from),
|
||||
rsnd_mod_name(mod_to), rsnd_mod_id(mod_to));
|
||||
|
||||
return dma->ops->init(io, dma, id, mod_from, mod_to);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ struct rsnd_dvc {
|
||||
struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */
|
||||
};
|
||||
|
||||
#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
|
||||
#define rsnd_dvc_of_node(priv) \
|
||||
of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc")
|
||||
|
||||
@ -63,6 +64,19 @@ static const char * const dvc_ramp_rate[] = {
|
||||
"0.125 dB/8192 steps", /* 10111 */
|
||||
};
|
||||
|
||||
static void rsnd_dvc_soft_reset(struct rsnd_mod *mod)
|
||||
{
|
||||
rsnd_mod_write(mod, DVC_SWRSR, 0);
|
||||
rsnd_mod_write(mod, DVC_SWRSR, 1);
|
||||
}
|
||||
|
||||
#define rsnd_dvc_initialize_lock(mod) __rsnd_dvc_initialize_lock(mod, 1)
|
||||
#define rsnd_dvc_initialize_unlock(mod) __rsnd_dvc_initialize_lock(mod, 0)
|
||||
static void __rsnd_dvc_initialize_lock(struct rsnd_mod *mod, u32 enable)
|
||||
{
|
||||
rsnd_mod_write(mod, DVC_DVUIR, enable);
|
||||
}
|
||||
|
||||
static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
|
||||
struct rsnd_mod *mod)
|
||||
{
|
||||
@ -135,49 +149,24 @@ static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
|
||||
static int rsnd_dvc_init(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
int dvc_id = rsnd_mod_id(dvc_mod);
|
||||
int src_id = rsnd_mod_id(src_mod);
|
||||
u32 route[] = {
|
||||
[0] = 0x30000,
|
||||
[1] = 0x30001,
|
||||
[2] = 0x40000,
|
||||
[3] = 0x10000,
|
||||
[4] = 0x20000,
|
||||
[5] = 0x40100
|
||||
};
|
||||
rsnd_mod_hw_start(mod);
|
||||
|
||||
if (src_id >= ARRAY_SIZE(route)) {
|
||||
dev_err(dev, "DVC%d isn't connected to SRC%d\n", dvc_id, src_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
rsnd_dvc_soft_reset(mod);
|
||||
|
||||
rsnd_mod_hw_start(dvc_mod);
|
||||
rsnd_dvc_initialize_lock(mod);
|
||||
|
||||
/*
|
||||
* fixme
|
||||
* it doesn't support CTU/MIX
|
||||
*/
|
||||
rsnd_mod_write(dvc_mod, CMD_ROUTE_SLCT, route[src_id]);
|
||||
rsnd_path_parse(priv, io);
|
||||
|
||||
rsnd_mod_write(dvc_mod, DVC_SWRSR, 0);
|
||||
rsnd_mod_write(dvc_mod, DVC_SWRSR, 1);
|
||||
|
||||
rsnd_mod_write(dvc_mod, DVC_DVUIR, 1);
|
||||
|
||||
rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod, io));
|
||||
rsnd_mod_write(mod, DVC_ADINR, rsnd_get_adinr_bit(mod, io));
|
||||
|
||||
/* ch0/ch1 Volume */
|
||||
rsnd_dvc_volume_update(io, dvc_mod);
|
||||
rsnd_dvc_volume_update(io, mod);
|
||||
|
||||
rsnd_mod_write(dvc_mod, DVC_DVUIR, 0);
|
||||
|
||||
rsnd_adg_set_cmd_timsel_gen2(dvc_mod, io);
|
||||
rsnd_adg_set_cmd_timsel_gen2(mod, io);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -195,6 +184,8 @@ static int rsnd_dvc_start(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
rsnd_dvc_initialize_unlock(mod);
|
||||
|
||||
rsnd_mod_write(mod, CMD_CTRL, 0x10);
|
||||
|
||||
return 0;
|
||||
@ -341,23 +332,21 @@ int rsnd_dvc_probe(struct platform_device *pdev,
|
||||
char name[RSND_DVC_NAME_SIZE];
|
||||
int i, nr, ret;
|
||||
|
||||
rsnd_of_parse_dvc(pdev, of_data, priv);
|
||||
|
||||
nr = info->dvc_info_nr;
|
||||
if (!nr)
|
||||
return 0;
|
||||
|
||||
/* This driver doesn't support Gen1 at this point */
|
||||
if (rsnd_is_gen1(priv)) {
|
||||
dev_warn(dev, "CMD is not supported on Gen1\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rsnd_of_parse_dvc(pdev, of_data, priv);
|
||||
|
||||
nr = info->dvc_info_nr;
|
||||
if (!nr)
|
||||
return 0;
|
||||
|
||||
dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL);
|
||||
if (!dvc) {
|
||||
dev_err(dev, "CMD allocate failed\n");
|
||||
if (!dvc)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->dvc_nr = nr;
|
||||
priv->dvc = dvc;
|
||||
|
@ -103,6 +103,22 @@ void rsnd_write(struct rsnd_priv *priv,
|
||||
regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
|
||||
}
|
||||
|
||||
void rsnd_force_write(struct rsnd_priv *priv,
|
||||
struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg, u32 data)
|
||||
{
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
|
||||
|
||||
if (!rsnd_is_accessible_reg(priv, gen, reg))
|
||||
return;
|
||||
|
||||
dev_dbg(dev, "w %s[%d] - %4d : %08x\n",
|
||||
rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data);
|
||||
|
||||
regmap_fields_force_write(gen->regs[reg], rsnd_mod_id(mod), data);
|
||||
}
|
||||
|
||||
void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg, u32 mask, u32 data)
|
||||
{
|
||||
@ -200,12 +216,13 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
|
||||
/* FIXME: it needs SSI_MODE2/3 in the future */
|
||||
RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80),
|
||||
RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80),
|
||||
RSND_GEN_M_REG(BUSIF_DALIGN, 0x8, 0x80),
|
||||
RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8, 0x80),
|
||||
RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80),
|
||||
RSND_GEN_M_REG(INT_ENABLE, 0x18, 0x80),
|
||||
RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
|
||||
};
|
||||
struct rsnd_regmap_field_conf conf_scu[] = {
|
||||
RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20),
|
||||
RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20),
|
||||
RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
|
||||
RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
|
||||
RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20),
|
||||
@ -223,6 +240,18 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
|
||||
RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
|
||||
RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40),
|
||||
RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40),
|
||||
RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100),
|
||||
RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100),
|
||||
RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40),
|
||||
RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40),
|
||||
RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40),
|
||||
RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40),
|
||||
RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40),
|
||||
RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40),
|
||||
RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40),
|
||||
RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40),
|
||||
RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40),
|
||||
RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40),
|
||||
RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100),
|
||||
RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100),
|
||||
RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100),
|
||||
|
200
sound/soc/sh/rcar/mix.c
Normal file
200
sound/soc/sh/rcar/mix.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* mix.c
|
||||
*
|
||||
* Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include "rsnd.h"
|
||||
|
||||
#define MIX_NAME_SIZE 16
|
||||
#define MIX_NAME "mix"
|
||||
|
||||
struct rsnd_mix {
|
||||
struct rsnd_mix_platform_info *info; /* rcar_snd.h */
|
||||
struct rsnd_mod mod;
|
||||
};
|
||||
|
||||
#define rsnd_mix_nr(priv) ((priv)->mix_nr)
|
||||
#define for_each_rsnd_mix(pos, priv, i) \
|
||||
for ((i) = 0; \
|
||||
((i) < rsnd_mix_nr(priv)) && \
|
||||
((pos) = (struct rsnd_mix *)(priv)->mix + i); \
|
||||
i++)
|
||||
|
||||
|
||||
static void rsnd_mix_soft_reset(struct rsnd_mod *mod)
|
||||
{
|
||||
rsnd_mod_write(mod, MIX_SWRSR, 0);
|
||||
rsnd_mod_write(mod, MIX_SWRSR, 1);
|
||||
}
|
||||
|
||||
#define rsnd_mix_initialize_lock(mod) __rsnd_mix_initialize_lock(mod, 1)
|
||||
#define rsnd_mix_initialize_unlock(mod) __rsnd_mix_initialize_lock(mod, 0)
|
||||
static void __rsnd_mix_initialize_lock(struct rsnd_mod *mod, u32 enable)
|
||||
{
|
||||
rsnd_mod_write(mod, MIX_MIXIR, enable);
|
||||
}
|
||||
|
||||
static void rsnd_mix_volume_update(struct rsnd_dai_stream *io,
|
||||
struct rsnd_mod *mod)
|
||||
{
|
||||
|
||||
/* Disable MIX dB setting */
|
||||
rsnd_mod_write(mod, MIX_MDBER, 0);
|
||||
|
||||
rsnd_mod_write(mod, MIX_MDBAR, 0);
|
||||
rsnd_mod_write(mod, MIX_MDBBR, 0);
|
||||
rsnd_mod_write(mod, MIX_MDBCR, 0);
|
||||
rsnd_mod_write(mod, MIX_MDBDR, 0);
|
||||
|
||||
/* Enable MIX dB setting */
|
||||
rsnd_mod_write(mod, MIX_MDBER, 1);
|
||||
}
|
||||
|
||||
static int rsnd_mix_init(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
rsnd_mod_hw_start(mod);
|
||||
|
||||
rsnd_mix_soft_reset(mod);
|
||||
|
||||
rsnd_mix_initialize_lock(mod);
|
||||
|
||||
rsnd_mod_write(mod, MIX_ADINR, rsnd_get_adinr_chan(mod, io));
|
||||
|
||||
rsnd_path_parse(priv, io);
|
||||
|
||||
/* volume step */
|
||||
rsnd_mod_write(mod, MIX_MIXMR, 0);
|
||||
rsnd_mod_write(mod, MIX_MVPDR, 0);
|
||||
|
||||
rsnd_mix_volume_update(io, mod);
|
||||
|
||||
rsnd_mix_initialize_unlock(mod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsnd_mix_quit(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
rsnd_mod_hw_stop(mod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rsnd_mod_ops rsnd_mix_ops = {
|
||||
.name = MIX_NAME,
|
||||
.init = rsnd_mix_init,
|
||||
.quit = rsnd_mix_quit,
|
||||
};
|
||||
|
||||
struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id)
|
||||
{
|
||||
if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
|
||||
id = 0;
|
||||
|
||||
return &((struct rsnd_mix *)(priv->mix) + id)->mod;
|
||||
}
|
||||
|
||||
static void rsnd_of_parse_mix(struct platform_device *pdev,
|
||||
const struct rsnd_of_data *of_data,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
struct device_node *node;
|
||||
struct rsnd_mix_platform_info *mix_info;
|
||||
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
|
||||
struct device *dev = &pdev->dev;
|
||||
int nr;
|
||||
|
||||
if (!of_data)
|
||||
return;
|
||||
|
||||
node = of_get_child_by_name(dev->of_node, "rcar_sound,mix");
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
nr = of_get_child_count(node);
|
||||
if (!nr)
|
||||
goto rsnd_of_parse_mix_end;
|
||||
|
||||
mix_info = devm_kzalloc(dev,
|
||||
sizeof(struct rsnd_mix_platform_info) * nr,
|
||||
GFP_KERNEL);
|
||||
if (!mix_info) {
|
||||
dev_err(dev, "mix info allocation error\n");
|
||||
goto rsnd_of_parse_mix_end;
|
||||
}
|
||||
|
||||
info->mix_info = mix_info;
|
||||
info->mix_info_nr = nr;
|
||||
|
||||
rsnd_of_parse_mix_end:
|
||||
of_node_put(node);
|
||||
|
||||
}
|
||||
|
||||
int rsnd_mix_probe(struct platform_device *pdev,
|
||||
const struct rsnd_of_data *of_data,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
|
||||
struct device *dev = rsnd_priv_to_dev(priv);
|
||||
struct rsnd_mix *mix;
|
||||
struct clk *clk;
|
||||
char name[MIX_NAME_SIZE];
|
||||
int i, nr, ret;
|
||||
|
||||
/* This driver doesn't support Gen1 at this point */
|
||||
if (rsnd_is_gen1(priv)) {
|
||||
dev_warn(dev, "MIX is not supported on Gen1\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rsnd_of_parse_mix(pdev, of_data, priv);
|
||||
|
||||
nr = info->mix_info_nr;
|
||||
if (!nr)
|
||||
return 0;
|
||||
|
||||
mix = devm_kzalloc(dev, sizeof(*mix) * nr, GFP_KERNEL);
|
||||
if (!mix)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->mix_nr = nr;
|
||||
priv->mix = mix;
|
||||
|
||||
for_each_rsnd_mix(mix, priv, i) {
|
||||
snprintf(name, MIX_NAME_SIZE, "%s.%d",
|
||||
MIX_NAME, i);
|
||||
|
||||
clk = devm_clk_get(dev, name);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
mix->info = &info->mix_info[i];
|
||||
|
||||
ret = rsnd_mod_init(priv, &mix->mod, &rsnd_mix_ops,
|
||||
clk, RSND_MOD_MIX, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rsnd_mix_remove(struct platform_device *pdev,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
struct rsnd_mix *mix;
|
||||
int i;
|
||||
|
||||
for_each_rsnd_mix(mix, priv, i) {
|
||||
rsnd_mod_quit(&mix->mod);
|
||||
}
|
||||
}
|
@ -47,6 +47,18 @@ enum rsnd_reg {
|
||||
RSND_REG_SCU_SYS_STATUS0,
|
||||
RSND_REG_SCU_SYS_INT_EN0,
|
||||
RSND_REG_CMD_ROUTE_SLCT,
|
||||
RSND_REG_CTU_CTUIR,
|
||||
RSND_REG_CTU_ADINR,
|
||||
RSND_REG_MIX_SWRSR,
|
||||
RSND_REG_MIX_MIXIR,
|
||||
RSND_REG_MIX_ADINR,
|
||||
RSND_REG_MIX_MIXMR,
|
||||
RSND_REG_MIX_MVPDR,
|
||||
RSND_REG_MIX_MDBAR,
|
||||
RSND_REG_MIX_MDBBR,
|
||||
RSND_REG_MIX_MDBCR,
|
||||
RSND_REG_MIX_MDBDR,
|
||||
RSND_REG_MIX_MDBER,
|
||||
RSND_REG_DVC_SWRSR,
|
||||
RSND_REG_DVC_DVUIR,
|
||||
RSND_REG_DVC_ADINR,
|
||||
@ -99,6 +111,7 @@ enum rsnd_reg {
|
||||
RSND_REG_SHARE26,
|
||||
RSND_REG_SHARE27,
|
||||
RSND_REG_SHARE28,
|
||||
RSND_REG_SHARE29,
|
||||
|
||||
RSND_REG_MAX,
|
||||
};
|
||||
@ -119,7 +132,7 @@ enum rsnd_reg {
|
||||
#define RSND_REG_SSI_CTRL RSND_REG_SHARE02
|
||||
#define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03
|
||||
#define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04
|
||||
#define RSND_REG_INT_ENABLE RSND_REG_SHARE05
|
||||
#define RSND_REG_SSI_INT_ENABLE RSND_REG_SHARE05
|
||||
#define RSND_REG_SRC_BSDSR RSND_REG_SHARE06
|
||||
#define RSND_REG_SRC_BSISR RSND_REG_SHARE07
|
||||
#define RSND_REG_DIV_EN RSND_REG_SHARE08
|
||||
@ -136,13 +149,14 @@ enum rsnd_reg {
|
||||
#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19
|
||||
#define RSND_REG_CMD_CTRL RSND_REG_SHARE20
|
||||
#define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21
|
||||
#define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22
|
||||
#define RSND_REG_SSI_BUSIF_DALIGN RSND_REG_SHARE22
|
||||
#define RSND_REG_DVC_VRCTR RSND_REG_SHARE23
|
||||
#define RSND_REG_DVC_VRPDR RSND_REG_SHARE24
|
||||
#define RSND_REG_DVC_VRDBR RSND_REG_SHARE25
|
||||
#define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26
|
||||
#define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27
|
||||
#define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28
|
||||
#define RSND_REG_SRC_BUSIF_DALIGN RSND_REG_SHARE29
|
||||
|
||||
struct rsnd_of_data;
|
||||
struct rsnd_priv;
|
||||
@ -157,27 +171,28 @@ struct rsnd_dai_stream;
|
||||
rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r)
|
||||
#define rsnd_mod_write(m, r, d) \
|
||||
rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d)
|
||||
#define rsnd_mod_force_write(m, r, d) \
|
||||
rsnd_force_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d)
|
||||
#define rsnd_mod_bset(m, r, s, d) \
|
||||
rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
|
||||
|
||||
u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
|
||||
void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg, u32 data);
|
||||
void rsnd_force_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
|
||||
enum rsnd_reg reg, u32 data);
|
||||
void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
|
||||
u32 mask, u32 data);
|
||||
u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
|
||||
u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
|
||||
u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
|
||||
u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
|
||||
void rsnd_path_parse(struct rsnd_priv *priv,
|
||||
struct rsnd_dai_stream *io);
|
||||
|
||||
/*
|
||||
* R-Car DMA
|
||||
*/
|
||||
struct rsnd_dma;
|
||||
struct rsnd_dma_ops {
|
||||
void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
|
||||
void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
|
||||
int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id,
|
||||
struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
|
||||
void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
|
||||
};
|
||||
|
||||
struct rsnd_dmaen {
|
||||
struct dma_chan *chan;
|
||||
@ -217,6 +232,8 @@ struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
|
||||
*/
|
||||
enum rsnd_mod_type {
|
||||
RSND_MOD_DVC = 0,
|
||||
RSND_MOD_MIX,
|
||||
RSND_MOD_CTU,
|
||||
RSND_MOD_SRC,
|
||||
RSND_MOD_SSI,
|
||||
RSND_MOD_MAX,
|
||||
@ -312,7 +329,7 @@ struct rsnd_mod {
|
||||
|
||||
#define rsnd_mod_to_priv(mod) ((mod)->priv)
|
||||
#define rsnd_mod_to_dma(mod) (&(mod)->dma)
|
||||
#define rsnd_mod_id(mod) ((mod)->id)
|
||||
#define rsnd_mod_id(mod) ((mod) ? (mod)->id : -1)
|
||||
#define rsnd_mod_hw_start(mod) clk_enable((mod)->clk)
|
||||
#define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk)
|
||||
|
||||
@ -345,9 +362,12 @@ struct rsnd_dai_stream {
|
||||
int byte_per_period;
|
||||
int next_period_byte;
|
||||
};
|
||||
#define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI])
|
||||
#define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC])
|
||||
#define rsnd_io_to_mod_dvc(io) ((io)->mod[RSND_MOD_DVC])
|
||||
#define rsnd_io_to_mod(io, i) ((i) < RSND_MOD_MAX ? (io)->mod[(i)] : NULL)
|
||||
#define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI)
|
||||
#define rsnd_io_to_mod_src(io) rsnd_io_to_mod((io), RSND_MOD_SRC)
|
||||
#define rsnd_io_to_mod_ctu(io) rsnd_io_to_mod((io), RSND_MOD_CTU)
|
||||
#define rsnd_io_to_mod_mix(io) rsnd_io_to_mod((io), RSND_MOD_MIX)
|
||||
#define rsnd_io_to_mod_dvc(io) rsnd_io_to_mod((io), RSND_MOD_DVC)
|
||||
#define rsnd_io_to_rdai(io) ((io)->rdai)
|
||||
#define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io)))
|
||||
#define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io)
|
||||
@ -436,12 +456,6 @@ struct rsnd_priv {
|
||||
*/
|
||||
void *gen;
|
||||
|
||||
/*
|
||||
* below value will be filled on rsnd_src_probe()
|
||||
*/
|
||||
void *src;
|
||||
int src_nr;
|
||||
|
||||
/*
|
||||
* below value will be filled on rsnd_adg_probe()
|
||||
*/
|
||||
@ -458,6 +472,24 @@ struct rsnd_priv {
|
||||
void *ssi;
|
||||
int ssi_nr;
|
||||
|
||||
/*
|
||||
* below value will be filled on rsnd_src_probe()
|
||||
*/
|
||||
void *src;
|
||||
int src_nr;
|
||||
|
||||
/*
|
||||
* below value will be filled on rsnd_ctu_probe()
|
||||
*/
|
||||
void *ctu;
|
||||
int ctu_nr;
|
||||
|
||||
/*
|
||||
* below value will be filled on rsnd_mix_probe()
|
||||
*/
|
||||
void *mix;
|
||||
int mix_nr;
|
||||
|
||||
/*
|
||||
* below value will be filled on rsnd_dvc_probe()
|
||||
*/
|
||||
@ -530,6 +562,19 @@ int rsnd_kctrl_new_e(struct rsnd_mod *mod,
|
||||
const char * const *texts,
|
||||
u32 max);
|
||||
|
||||
/*
|
||||
* R-Car SSI
|
||||
*/
|
||||
int rsnd_ssi_probe(struct platform_device *pdev,
|
||||
const struct rsnd_of_data *of_data,
|
||||
struct rsnd_priv *priv);
|
||||
void rsnd_ssi_remove(struct platform_device *pdev,
|
||||
struct rsnd_priv *priv);
|
||||
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
|
||||
int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
|
||||
int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
|
||||
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
|
||||
|
||||
/*
|
||||
* R-Car SRC
|
||||
*/
|
||||
@ -550,20 +595,27 @@ int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
|
||||
int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod);
|
||||
int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod);
|
||||
|
||||
#define rsnd_src_nr(priv) ((priv)->src_nr)
|
||||
|
||||
/*
|
||||
* R-Car SSI
|
||||
* R-Car CTU
|
||||
*/
|
||||
int rsnd_ssi_probe(struct platform_device *pdev,
|
||||
int rsnd_ctu_probe(struct platform_device *pdev,
|
||||
const struct rsnd_of_data *of_data,
|
||||
struct rsnd_priv *priv);
|
||||
void rsnd_ssi_remove(struct platform_device *pdev,
|
||||
|
||||
void rsnd_ctu_remove(struct platform_device *pdev,
|
||||
struct rsnd_priv *priv);
|
||||
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
|
||||
int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
|
||||
int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
|
||||
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
|
||||
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
|
||||
|
||||
/*
|
||||
* R-Car MIX
|
||||
*/
|
||||
int rsnd_mix_probe(struct platform_device *pdev,
|
||||
const struct rsnd_of_data *of_data,
|
||||
struct rsnd_priv *priv);
|
||||
|
||||
void rsnd_mix_remove(struct platform_device *pdev,
|
||||
struct rsnd_priv *priv);
|
||||
struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
|
||||
|
||||
/*
|
||||
* R-Car DVC
|
||||
@ -575,7 +627,4 @@ void rsnd_dvc_remove(struct platform_device *pdev,
|
||||
struct rsnd_priv *priv);
|
||||
struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
|
||||
|
||||
#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -41,6 +41,7 @@ static const struct rsrc_card_of_data routes_of_ssi0_ak4642 = {
|
||||
static const struct of_device_id rsrc_card_of_match[] = {
|
||||
{ .compatible = "renesas,rsrc-card,lager", .data = &routes_of_ssi0_ak4642 },
|
||||
{ .compatible = "renesas,rsrc-card,koelsch", .data = &routes_of_ssi0_ak4642 },
|
||||
{ .compatible = "renesas,rsrc-card", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rsrc_card_of_match);
|
||||
@ -242,8 +243,15 @@ static int rsrc_card_parse_links(struct device_node *np,
|
||||
snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name);
|
||||
|
||||
/* additional name prefix */
|
||||
priv->codec_conf.of_node = dai_link->codec_of_node;
|
||||
priv->codec_conf.name_prefix = of_data->prefix;
|
||||
if (of_data) {
|
||||
priv->codec_conf.of_node = dai_link->codec_of_node;
|
||||
priv->codec_conf.name_prefix = of_data->prefix;
|
||||
} else {
|
||||
snd_soc_of_parse_audio_prefix(&priv->snd_card,
|
||||
&priv->codec_conf,
|
||||
dai_link->codec_of_node,
|
||||
"audio-prefix");
|
||||
}
|
||||
|
||||
/* set dai_name */
|
||||
snprintf(dai_props->dai_name, DAI_NAME_NUM, "be.%s",
|
||||
@ -361,8 +369,14 @@ static int rsrc_card_parse_of(struct device_node *node,
|
||||
priv->snd_card.num_links = num;
|
||||
priv->snd_card.codec_conf = &priv->codec_conf;
|
||||
priv->snd_card.num_configs = 1;
|
||||
priv->snd_card.of_dapm_routes = of_data->routes;
|
||||
priv->snd_card.num_of_dapm_routes = of_data->num_routes;
|
||||
|
||||
if (of_data) {
|
||||
priv->snd_card.of_dapm_routes = of_data->routes;
|
||||
priv->snd_card.num_of_dapm_routes = of_data->num_routes;
|
||||
} else {
|
||||
snd_soc_of_parse_audio_routing(&priv->snd_card,
|
||||
"audio-routing");
|
||||
}
|
||||
|
||||
/* Parse the card name from DT */
|
||||
snd_soc_of_parse_card_name(&priv->snd_card, "card-name");
|
||||
|
@ -30,6 +30,7 @@ struct rsnd_src {
|
||||
|
||||
#define RSND_SRC_NAME_SIZE 16
|
||||
|
||||
#define rsnd_src_nr(priv) ((priv)->src_nr)
|
||||
#define rsnd_enable_sync_convert(src) ((src)->sen.val)
|
||||
#define rsnd_src_of_node(priv) \
|
||||
of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src")
|
||||
@ -117,6 +118,20 @@ struct rsnd_src {
|
||||
/*
|
||||
* Gen1/Gen2 common functions
|
||||
*/
|
||||
static void rsnd_src_soft_reset(struct rsnd_mod *mod)
|
||||
{
|
||||
rsnd_mod_write(mod, SRC_SWRSR, 0);
|
||||
rsnd_mod_write(mod, SRC_SWRSR, 1);
|
||||
}
|
||||
|
||||
|
||||
#define rsnd_src_initialize_lock(mod) __rsnd_src_initialize_lock(mod, 1)
|
||||
#define rsnd_src_initialize_unlock(mod) __rsnd_src_initialize_lock(mod, 0)
|
||||
static void __rsnd_src_initialize_lock(struct rsnd_mod *mod, u32 enable)
|
||||
{
|
||||
rsnd_mod_write(mod, SRC_SRCIR, enable);
|
||||
}
|
||||
|
||||
static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
|
||||
struct rsnd_mod *mod)
|
||||
{
|
||||
@ -133,7 +148,6 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
|
||||
int use_busif)
|
||||
{
|
||||
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
|
||||
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
|
||||
int ssi_id = rsnd_mod_id(ssi_mod);
|
||||
|
||||
/*
|
||||
@ -170,27 +184,14 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
|
||||
* DMA settings for SSIU
|
||||
*/
|
||||
if (use_busif) {
|
||||
u32 val = 0x76543210;
|
||||
u32 mask = ~0;
|
||||
u32 val = rsnd_get_dalign(ssi_mod, io);
|
||||
|
||||
rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR,
|
||||
rsnd_get_adinr(ssi_mod, io));
|
||||
rsnd_get_adinr_bit(ssi_mod, io));
|
||||
rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1);
|
||||
rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1);
|
||||
|
||||
mask <<= runtime->channels * 4;
|
||||
val = val & mask;
|
||||
|
||||
switch (runtime->sample_bits) {
|
||||
case 16:
|
||||
val |= 0x67452301 & ~mask;
|
||||
break;
|
||||
case 32:
|
||||
val |= 0x76543210 & ~mask;
|
||||
break;
|
||||
}
|
||||
rsnd_mod_write(ssi_mod, BUSIF_DALIGN, val);
|
||||
|
||||
rsnd_mod_write(ssi_mod, SSI_BUSIF_DALIGN, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -215,10 +216,9 @@ int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod)
|
||||
return 0;
|
||||
|
||||
/* enable SSI interrupt if Gen2 */
|
||||
if (rsnd_ssi_is_dma_mode(ssi_mod))
|
||||
rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0e000000);
|
||||
else
|
||||
rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000);
|
||||
rsnd_mod_write(ssi_mod, SSI_INT_ENABLE,
|
||||
rsnd_ssi_is_dma_mode(ssi_mod) ?
|
||||
0x0e000000 : 0x0f000000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -231,7 +231,7 @@ int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod)
|
||||
return 0;
|
||||
|
||||
/* disable SSI interrupt if Gen2 */
|
||||
rsnd_mod_write(ssi_mod, INT_ENABLE, 0x00000000);
|
||||
rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, 0x00000000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -294,12 +294,8 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
|
||||
if (convert_rate)
|
||||
fsrate = 0x0400000 / convert_rate * runtime->rate;
|
||||
|
||||
/* set/clear soft reset */
|
||||
rsnd_mod_write(mod, SRC_SWRSR, 0);
|
||||
rsnd_mod_write(mod, SRC_SWRSR, 1);
|
||||
|
||||
/* Set channel number and output bit length */
|
||||
rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod, io));
|
||||
rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr_bit(mod, io));
|
||||
|
||||
/* Enable the initial value of IFS */
|
||||
if (fsrate) {
|
||||
@ -358,17 +354,15 @@ static int rsnd_src_init(struct rsnd_mod *mod,
|
||||
|
||||
rsnd_mod_hw_start(mod);
|
||||
|
||||
rsnd_src_soft_reset(mod);
|
||||
|
||||
rsnd_src_initialize_lock(mod);
|
||||
|
||||
src->err = 0;
|
||||
|
||||
/* reset sync convert_rate */
|
||||
src->sync.val = 0;
|
||||
|
||||
/*
|
||||
* Initialize the operation of the SRC internal circuits
|
||||
* see rsnd_src_start()
|
||||
*/
|
||||
rsnd_mod_write(mod, SRC_SRCIR, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -395,11 +389,7 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
|
||||
|
||||
static int rsnd_src_start(struct rsnd_mod *mod)
|
||||
{
|
||||
/*
|
||||
* Cancel the initialization and operate the SRC function
|
||||
* see rsnd_src_init()
|
||||
*/
|
||||
rsnd_mod_write(mod, SRC_SRCIR, 0);
|
||||
rsnd_src_initialize_unlock(mod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -617,6 +607,14 @@ static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable)
|
||||
int_val = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* WORKAROUND
|
||||
*
|
||||
* ignore over flow error when rsnd_enable_sync_convert()
|
||||
*/
|
||||
if (rsnd_enable_sync_convert(src))
|
||||
sys_int_val = sys_int_val & 0xffff;
|
||||
|
||||
rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
|
||||
rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
|
||||
rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
|
||||
@ -632,11 +630,22 @@ static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod)
|
||||
|
||||
static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod)
|
||||
{
|
||||
u32 val = OUF_SRC(rsnd_mod_id(mod));
|
||||
struct rsnd_src *src = rsnd_mod_to_src(mod);
|
||||
u32 val0, val1;
|
||||
bool ret = false;
|
||||
|
||||
if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val) ||
|
||||
(rsnd_mod_read(mod, SCU_SYS_STATUS1) & val)) {
|
||||
val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
|
||||
|
||||
/*
|
||||
* WORKAROUND
|
||||
*
|
||||
* ignore over flow error when rsnd_enable_sync_convert()
|
||||
*/
|
||||
if (rsnd_enable_sync_convert(src))
|
||||
val0 = val0 & 0xffff;
|
||||
|
||||
if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) ||
|
||||
(rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) {
|
||||
struct rsnd_src *src = rsnd_mod_to_src(mod);
|
||||
|
||||
src->err++;
|
||||
@ -652,7 +661,20 @@ static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod)
|
||||
static int _rsnd_src_start_gen2(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io)
|
||||
{
|
||||
u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11;
|
||||
struct rsnd_src *src = rsnd_mod_to_src(mod);
|
||||
u32 val;
|
||||
|
||||
val = rsnd_get_dalign(mod, io);
|
||||
|
||||
rsnd_mod_write(mod, SRC_BUSIF_DALIGN, val);
|
||||
|
||||
/*
|
||||
* WORKAROUND
|
||||
*
|
||||
* Enable SRC output if you want to use sync convert together with DVC
|
||||
*/
|
||||
val = (rsnd_io_to_mod_dvc(io) && !rsnd_enable_sync_convert(src)) ?
|
||||
0x01 : 0x11;
|
||||
|
||||
rsnd_mod_write(mod, SRC_CTRL, val);
|
||||
|
||||
@ -921,13 +943,6 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod,
|
||||
if (!rsnd_rdai_is_clk_master(rdai))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We can't use SRC sync convert
|
||||
* if it has DVC
|
||||
*/
|
||||
if (rsnd_io_to_mod_dvc(io))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* enable sync convert
|
||||
*/
|
||||
@ -1047,10 +1062,8 @@ int rsnd_src_probe(struct platform_device *pdev,
|
||||
return 0;
|
||||
|
||||
src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL);
|
||||
if (!src) {
|
||||
dev_err(dev, "SRC allocate failed\n");
|
||||
if (!src)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->src_nr = nr;
|
||||
priv->src = src;
|
||||
|
@ -770,10 +770,8 @@ int rsnd_ssi_probe(struct platform_device *pdev,
|
||||
*/
|
||||
nr = info->ssi_info_nr;
|
||||
ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL);
|
||||
if (!ssi) {
|
||||
dev_err(dev, "SSI allocate failed\n");
|
||||
if (!ssi)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->ssi = ssi;
|
||||
priv->ssi_nr = nr;
|
||||
|
Loading…
Reference in New Issue
Block a user