Skip to content

V3.14 mx6 spdif #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions arch/arm/boot/dts/imx6dl-hummingboard.dts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,16 @@
&spdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hummingboard_spdif>;
clocks = <&clks 197>, <&clks 0>,
<&clks 197>, <&clks 0>,
<&clks 0>, <&clks 0>,
<&clks 0>, <&clks 0>,
<&clks 0>;
clock-names = "core", "rxtx0",
"rxtx1", "rxtx2",
"rxtx3", "rxtx4",
"rxtx5", "rxtx6",
"rxtx7";
status = "okay";
};

Expand Down
10 changes: 10 additions & 0 deletions arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,16 @@
&spdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_cubox_i_spdif>;
clocks = <&clks 197>, <&clks 0>,
<&clks 197>, <&clks 0>,
<&clks 0>, <&clks 0>,
<&clks 0>, <&clks 0>,
<&clks 0>;
clock-names = "core", "rxtx0",
"rxtx1", "rxtx2",
"rxtx3", "rxtx4",
"rxtx5", "rxtx6",
"rxtx7";
status = "okay";
};

Expand Down
2 changes: 1 addition & 1 deletion sound/soc/codecs/spdif_transmitter.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

#define DRV_NAME "spdif-dit"

#define STUB_RATES SNDRV_PCM_RATE_8000_96000
#define STUB_RATES SNDRV_PCM_RATE_8000_192000
#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
Expand Down
78 changes: 53 additions & 25 deletions sound/soc/fsl/fsl_spdif.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct spdif_mixer_control {
spinlock_t ctl_lock;

/* IEC958 channel tx status bit */
unsigned char ch_status[4];
unsigned char ch_status[6];

/* User bits */
unsigned char subcode[2 * SPDIF_UBITS_SIZE];
Expand Down Expand Up @@ -297,11 +297,11 @@ static int spdif_softreset(struct fsl_spdif_priv *spdif_priv)
return -EBUSY;
}

static void spdif_set_cstatus(struct spdif_mixer_control *ctrl,
u8 mask, u8 cstatus)
static inline void spdif_set_cstatus(struct spdif_mixer_control *ctrl,
u8 byteno, u8 mask, u8 cstatus)
{
ctrl->ch_status[3] &= ~mask;
ctrl->ch_status[3] |= cstatus & mask;
ctrl->ch_status[byteno] &= ~mask;
ctrl->ch_status[byteno] |= cstatus & mask;
}

static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv)
Expand All @@ -318,10 +318,16 @@ static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv)

dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status);

ch_status = bitrev8(ctrl->ch_status[3]) << 16;
ch_status = bitrev8(ctrl->ch_status[3]) << 16 |
(bitrev8(ctrl->ch_status[4]) << 8) |
bitrev8(ctrl->ch_status[5]);
regmap_write(regmap, REG_SPDIF_STCSCL, ch_status);

dev_dbg(&pdev->dev, "STCSCL: 0x%06x\n", ch_status);

/* Set outgoing validity (0: pcm, 1: non-audio) */
regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_VAL_MASK,
(ctrl->ch_status[0] & IEC958_AES0_NONAUDIO) ? 0 : SCR_VAL_CLEAR);
}

/* Set SPDIF PhaseConfig register for rx clock */
Expand Down Expand Up @@ -349,23 +355,45 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
struct regmap *regmap = spdif_priv->regmap;
struct platform_device *pdev = spdif_priv->pdev;
unsigned long csfs = 0;
u32 stc, mask, rate;
u8 clk, div;
u8 clk, div, csfs, csofs;
int ret;

switch (sample_rate) {
case 32000:
rate = SPDIF_TXRATE_32000;
csfs = IEC958_AES3_CON_FS_32000;
csofs = IEC958_AES4_CON_ORIGFS_32000;
break;
case 44100:
rate = SPDIF_TXRATE_44100;
csfs = IEC958_AES3_CON_FS_44100;
csofs = IEC958_AES4_CON_ORIGFS_44100;
break;
case 48000:
rate = SPDIF_TXRATE_48000;
csfs = IEC958_AES3_CON_FS_48000;
csofs = IEC958_AES4_CON_ORIGFS_48000;
break;
case 88200:
rate = SPDIF_TXRATE_88200;
csfs = IEC958_AES3_CON_FS_88200;
csofs = IEC958_AES4_CON_ORIGFS_88200;
break;
case 96000:
rate = SPDIF_TXRATE_96000;
csfs = IEC958_AES3_CON_FS_96000;
csofs = IEC958_AES4_CON_ORIGFS_96000;
break;
case 176400:
rate = SPDIF_TXRATE_176400;
csfs = IEC958_AES3_CON_FS_176400;
csofs = IEC958_AES4_CON_ORIGFS_176400;
break;
case 192000:
rate = SPDIF_TXRATE_192000;
csfs = IEC958_AES3_CON_FS_192000;
csofs = IEC958_AES4_CON_ORIGFS_192000;
break;
default:
dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate);
Expand Down Expand Up @@ -401,7 +429,8 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
clk_get_rate(spdif_priv->txclk[rate]));

/* set fs field in consumer channel status */
spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs);
spdif_set_cstatus(ctrl, 3, IEC958_AES3_CON_FS, csfs);
spdif_set_cstatus(ctrl, 4, IEC958_AES4_CON_ORIGFS, csofs);

/* select clock source and divisor */
stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | STC_TXCLK_DIV(div);
Expand Down Expand Up @@ -511,8 +540,8 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream,
__func__, sample_rate);
return ret;
}
spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK,
IEC958_AES3_CON_CLOCK_1000PPM);
spdif_set_cstatus(ctrl, 3, IEC958_AES3_CON_CLOCK,
IEC958_AES3_CON_CLOCK_1000PPM);
spdif_write_channel_status(spdif_priv);
} else {
/* Setup rx clock source */
Expand Down Expand Up @@ -582,29 +611,27 @@ static int fsl_spdif_info(struct snd_kcontrol *kcontrol,
static int fsl_spdif_pb_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *uvalue)
{
int i;
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;

uvalue->value.iec958.status[0] = ctrl->ch_status[0];
uvalue->value.iec958.status[1] = ctrl->ch_status[1];
uvalue->value.iec958.status[2] = ctrl->ch_status[2];
uvalue->value.iec958.status[3] = ctrl->ch_status[3];
for (i = 0; i < ARRAY_SIZE(ctrl->ch_status); i++)
uvalue->value.iec958.status[i] = ctrl->ch_status[i];

return 0;
}

static int fsl_spdif_pb_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *uvalue)
{
int i;
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;

ctrl->ch_status[0] = uvalue->value.iec958.status[0];
ctrl->ch_status[1] = uvalue->value.iec958.status[1];
ctrl->ch_status[2] = uvalue->value.iec958.status[2];
ctrl->ch_status[3] = uvalue->value.iec958.status[3];
for (i = 0; i < ARRAY_SIZE(ctrl->ch_status); i++)
ctrl->ch_status[i] = uvalue->value.iec958.status[i];

spdif_write_channel_status(spdif_priv);

Expand Down Expand Up @@ -1005,7 +1032,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
struct clk *clk, u64 savesub,
enum spdif_txrate index)
{
const u32 rate[] = { 32000, 44100, 48000 };
const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400, 192000 };
u64 rate_ideal, rate_actual, sub;
u32 div, arate;

Expand All @@ -1023,15 +1050,15 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
break;
} else if (arate / rate[index] == 1) {
/* A little bigger than expect */
sub = (arate - rate[index]) * 100000;
sub = (u64)(arate - rate[index]) * 100000;
do_div(sub, rate[index]);
if (sub < savesub) {
savesub = sub;
spdif_priv->txclk_div[index] = div;
}
} else if (rate[index] / arate == 1) {
/* A little smaller than expect */
sub = (rate[index] - arate) * 100000;
sub = (u64)(rate[index] - arate) * 100000;
do_div(sub, rate[index]);
if (sub < savesub) {
savesub = sub;
Expand All @@ -1046,7 +1073,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
enum spdif_txrate index)
{
const u32 rate[] = { 32000, 44100, 48000 };
const u32 rate[] = { 32000, 44100, 48000, 88200, 96000, 176400, 192000 };
struct platform_device *pdev = spdif_priv->pdev;
struct device *dev = &pdev->dev;
u64 savesub = 100000, ret;
Expand Down Expand Up @@ -1156,12 +1183,13 @@ static int fsl_spdif_probe(struct platform_device *pdev)
spin_lock_init(&ctrl->ctl_lock);

/* Init tx channel status default value */
ctrl->ch_status[0] =
IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_5015;
ctrl->ch_status[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID;
ctrl->ch_status[2] = 0x00;
ctrl->ch_status[3] =
IEC958_AES3_CON_FS_44100 | IEC958_AES3_CON_CLOCK_1000PPM;
ctrl->ch_status[4] = IEC958_AES4_CON_ORIGFS_44100;
ctrl->ch_status[5] = IEC958_AES5_CON_CGMSA_COPYFREELY;

spdif_priv->dpll_locked = false;

Expand Down
12 changes: 10 additions & 2 deletions sound/soc/fsl/fsl_spdif.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,12 @@ enum spdif_txrate {
SPDIF_TXRATE_32000 = 0,
SPDIF_TXRATE_44100,
SPDIF_TXRATE_48000,
SPDIF_TXRATE_88200,
SPDIF_TXRATE_96000,
SPDIF_TXRATE_176400,
SPDIF_TXRATE_192000,
};
#define SPDIF_TXRATE_MAX (SPDIF_TXRATE_48000 + 1)
#define SPDIF_TXRATE_MAX (SPDIF_TXRATE_192000 + 1)


#define SPDIF_CSTATUS_BYTE 6
Expand All @@ -173,7 +177,11 @@ enum spdif_txrate {

#define FSL_SPDIF_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_88200 | \
SNDRV_PCM_RATE_96000 | \
SNDRV_PCM_RATE_176400| \
SNDRV_PCM_RATE_192000)

#define FSL_SPDIF_RATES_CAPTURE (SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_32000 | \
Expand Down