Skip to content

Commit 6d35e08

Browse files
committed
Merge remote-tracking branch 'takashi/for-next' into sound/upstream-20260428
2 parents 70783f1 + a895279 commit 6d35e08

7 files changed

Lines changed: 836 additions & 126 deletions

File tree

sound/isa/opti9xx/miro.c

Lines changed: 256 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,25 @@ MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
8888

8989
#define OPTi9XX_MC_REG(n) n
9090

91+
enum {
92+
MIRO_ACI_MASTER,
93+
MIRO_ACI_MIC,
94+
MIRO_ACI_LINE,
95+
MIRO_ACI_CD,
96+
MIRO_ACI_SYNTH,
97+
MIRO_ACI_PCM,
98+
MIRO_ACI_LINE1,
99+
MIRO_ACI_LINE2,
100+
MIRO_ACI_EQ1,
101+
MIRO_ACI_EQ2,
102+
MIRO_ACI_EQ3,
103+
MIRO_ACI_EQ4,
104+
MIRO_ACI_EQ5,
105+
MIRO_ACI_EQ6,
106+
MIRO_ACI_EQ7,
107+
MIRO_ACI_COUNT,
108+
};
109+
91110
struct snd_miro {
92111
unsigned short hardware;
93112
unsigned char password;
@@ -102,6 +121,7 @@ struct snd_miro {
102121

103122
spinlock_t lock;
104123
struct snd_pcm *pcm;
124+
struct snd_wss *codec;
105125

106126
long wss_base;
107127
int irq;
@@ -113,6 +133,12 @@ struct snd_miro {
113133

114134
struct snd_card *card;
115135
struct snd_miro_aci *aci;
136+
#ifdef CONFIG_PM
137+
unsigned char aci_saved[MIRO_ACI_COUNT][2];
138+
unsigned char aci_saved_amp;
139+
unsigned char aci_saved_preamp;
140+
unsigned char aci_saved_solomode;
141+
#endif
116142
};
117143

118144
static struct snd_miro_aci aci_device;
@@ -664,6 +690,44 @@ static const unsigned char aci_init_values[][2] = {
664690
{ ACI_SET_MASTER + 1, 0x20 },
665691
};
666692

693+
#ifdef CONFIG_PM
694+
static const unsigned char snd_miro_saved_get_regs[MIRO_ACI_COUNT] = {
695+
[MIRO_ACI_MASTER] = ACI_GET_MASTER,
696+
[MIRO_ACI_MIC] = ACI_GET_MIC,
697+
[MIRO_ACI_LINE] = ACI_GET_LINE,
698+
[MIRO_ACI_CD] = ACI_GET_CD,
699+
[MIRO_ACI_SYNTH] = ACI_GET_SYNTH,
700+
[MIRO_ACI_PCM] = ACI_GET_PCM,
701+
[MIRO_ACI_LINE1] = ACI_GET_LINE1,
702+
[MIRO_ACI_LINE2] = ACI_GET_LINE2,
703+
[MIRO_ACI_EQ1] = ACI_GET_EQ1,
704+
[MIRO_ACI_EQ2] = ACI_GET_EQ2,
705+
[MIRO_ACI_EQ3] = ACI_GET_EQ3,
706+
[MIRO_ACI_EQ4] = ACI_GET_EQ4,
707+
[MIRO_ACI_EQ5] = ACI_GET_EQ5,
708+
[MIRO_ACI_EQ6] = ACI_GET_EQ6,
709+
[MIRO_ACI_EQ7] = ACI_GET_EQ7,
710+
};
711+
712+
static const unsigned char snd_miro_saved_set_regs[MIRO_ACI_COUNT] = {
713+
[MIRO_ACI_MASTER] = ACI_SET_MASTER,
714+
[MIRO_ACI_MIC] = ACI_SET_MIC,
715+
[MIRO_ACI_LINE] = ACI_SET_LINE,
716+
[MIRO_ACI_CD] = ACI_SET_CD,
717+
[MIRO_ACI_SYNTH] = ACI_SET_SYNTH,
718+
[MIRO_ACI_PCM] = ACI_SET_PCM,
719+
[MIRO_ACI_LINE1] = ACI_SET_LINE1,
720+
[MIRO_ACI_LINE2] = ACI_SET_LINE2,
721+
[MIRO_ACI_EQ1] = ACI_SET_EQ1,
722+
[MIRO_ACI_EQ2] = ACI_SET_EQ2,
723+
[MIRO_ACI_EQ3] = ACI_SET_EQ3,
724+
[MIRO_ACI_EQ4] = ACI_SET_EQ4,
725+
[MIRO_ACI_EQ5] = ACI_SET_EQ5,
726+
[MIRO_ACI_EQ6] = ACI_SET_EQ6,
727+
[MIRO_ACI_EQ7] = ACI_SET_EQ7,
728+
};
729+
#endif
730+
667731
static int snd_set_aci_init_values(struct snd_miro *miro)
668732
{
669733
int idx, error;
@@ -702,11 +766,116 @@ static int snd_set_aci_init_values(struct snd_miro *miro)
702766
}
703767
aci->aci_amp = 0;
704768
aci->aci_preamp = 0;
705-
aci->aci_solomode = 1;
769+
aci->aci_solomode = 0;
770+
771+
return 0;
772+
}
773+
774+
static int snd_miro_aci_force_known_state(struct snd_miro_aci *aci)
775+
{
776+
int i, err;
777+
778+
for (i = 0; i < 3; i++) {
779+
err = snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1);
780+
if (err < 0)
781+
return err;
782+
}
706783

707784
return 0;
708785
}
709786

787+
static int snd_miro_aci_initialize(struct snd_miro_aci *aci)
788+
{
789+
int err;
790+
791+
err = snd_aci_cmd(aci, ACI_INIT, -1, -1);
792+
if (err < 0)
793+
return err;
794+
err = snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP);
795+
if (err < 0)
796+
return err;
797+
798+
return snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP);
799+
}
800+
801+
#ifdef CONFIG_PM
802+
static int snd_miro_save_aci_state(struct snd_miro *miro)
803+
{
804+
struct snd_miro_aci *aci = miro->aci;
805+
int i, limit, value;
806+
807+
limit = aci->aci_product == 'C' ? MIRO_ACI_COUNT : MIRO_ACI_LINE2 + 1;
808+
for (i = 0; i < limit; i++) {
809+
value = aci_getvalue(aci, snd_miro_saved_get_regs[i]);
810+
if (value < 0)
811+
return value;
812+
miro->aci_saved[i][1] = value;
813+
814+
value = aci_getvalue(aci, snd_miro_saved_get_regs[i] + 1);
815+
if (value < 0)
816+
return value;
817+
miro->aci_saved[i][0] = value;
818+
}
819+
820+
miro->aci_saved_amp = aci->aci_amp;
821+
if (aci->aci_version <= 176) {
822+
miro->aci_saved_preamp = aci->aci_preamp;
823+
} else {
824+
value = aci_getvalue(aci, ACI_GET_PREAMP);
825+
if (value < 0)
826+
return value;
827+
miro->aci_saved_preamp = value;
828+
}
829+
830+
value = aci_getvalue(aci, ACI_S_GENERAL);
831+
if (value < 0)
832+
return value;
833+
miro->aci_saved_solomode = !(value & 0x20);
834+
835+
return 0;
836+
}
837+
838+
static int snd_miro_restore_aci_state(struct snd_miro *miro)
839+
{
840+
struct snd_miro_aci *aci = miro->aci;
841+
int i, limit, err, left_reg;
842+
843+
err = snd_set_aci_init_values(miro);
844+
if (err < 0)
845+
return err;
846+
847+
limit = aci->aci_product == 'C' ? MIRO_ACI_COUNT : MIRO_ACI_LINE2 + 1;
848+
for (i = 0; i < limit; i++) {
849+
left_reg = snd_miro_saved_set_regs[i] == ACI_SET_MASTER ?
850+
snd_miro_saved_set_regs[i] + 1 :
851+
snd_miro_saved_set_regs[i] + 8;
852+
err = aci_setvalue(aci, left_reg, miro->aci_saved[i][0]);
853+
if (err < 0)
854+
return err;
855+
err = aci_setvalue(aci, snd_miro_saved_set_regs[i],
856+
miro->aci_saved[i][1]);
857+
if (err < 0)
858+
return err;
859+
}
860+
861+
err = aci_setvalue(aci, ACI_SET_POWERAMP, miro->aci_saved_amp);
862+
if (err < 0)
863+
return err;
864+
err = aci_setvalue(aci, ACI_SET_PREAMP, miro->aci_saved_preamp);
865+
if (err < 0)
866+
return err;
867+
err = aci_setvalue(aci, ACI_SET_SOLOMODE, miro->aci_saved_solomode);
868+
if (err < 0)
869+
return err;
870+
871+
aci->aci_amp = miro->aci_saved_amp;
872+
aci->aci_preamp = miro->aci_saved_preamp;
873+
aci->aci_solomode = miro->aci_saved_solomode;
874+
875+
return 0;
876+
}
877+
#endif
878+
710879
static int snd_miro_mixer(struct snd_card *card,
711880
struct snd_miro *miro)
712881
{
@@ -1203,7 +1372,7 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
12031372
struct snd_miro *miro)
12041373
{
12051374
unsigned char regval;
1206-
int i;
1375+
int err;
12071376
struct snd_miro_aci *aci = &aci_device;
12081377

12091378
miro->aci = aci;
@@ -1224,12 +1393,12 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
12241393
return -ENOMEM;
12251394
}
12261395

1227-
/* force ACI into a known state */
1228-
for (i = 0; i < 3; i++)
1229-
if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) {
1230-
dev_err(card->dev, "can't force aci into known state.\n");
1231-
return -ENXIO;
1232-
}
1396+
/* force ACI into a known state */
1397+
err = snd_miro_aci_force_known_state(aci);
1398+
if (err < 0) {
1399+
dev_err(card->dev, "can't force aci into known state.\n");
1400+
return -ENXIO;
1401+
}
12331402

12341403
aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1);
12351404
aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1);
@@ -1246,9 +1415,8 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
12461415
return -ENXIO;
12471416
}
12481417

1249-
if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 ||
1250-
snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 ||
1251-
snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) {
1418+
err = snd_miro_aci_initialize(aci);
1419+
if (err < 0) {
12521420
dev_err(card->dev, "can't initialize aci.\n");
12531421
return -ENXIO;
12541422
}
@@ -1299,6 +1467,7 @@ static int snd_miro_probe(struct snd_card *card)
12991467
WSS_HW_DETECT, 0, &codec);
13001468
if (error < 0)
13011469
return error;
1470+
miro->codec = codec;
13021471

13031472
error = snd_wss_pcm(codec, 0);
13041473
if (error < 0)
@@ -1408,6 +1577,7 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
14081577
return error;
14091578

14101579
miro = card->private_data;
1580+
miro->card = card;
14111581

14121582
error = snd_card_miro_detect(card, miro);
14131583
if (error < 0) {
@@ -1470,12 +1640,69 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
14701640
return 0;
14711641
}
14721642

1643+
#ifdef CONFIG_PM
1644+
static int snd_miro_suspend(struct snd_card *card)
1645+
{
1646+
struct snd_miro *miro = card->private_data;
1647+
int error;
1648+
1649+
error = snd_miro_save_aci_state(miro);
1650+
if (error < 0)
1651+
return error;
1652+
1653+
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1654+
miro->codec->suspend(miro->codec);
1655+
return 0;
1656+
}
1657+
1658+
static int snd_miro_resume(struct snd_card *card)
1659+
{
1660+
struct snd_miro *miro = card->private_data;
1661+
int error;
1662+
1663+
error = snd_miro_configure(miro);
1664+
if (error < 0)
1665+
return error;
1666+
error = snd_miro_aci_force_known_state(miro->aci);
1667+
if (error < 0) {
1668+
dev_err(card->dev, "can't force aci into known state\n");
1669+
return error;
1670+
}
1671+
error = snd_miro_aci_initialize(miro->aci);
1672+
if (error < 0) {
1673+
dev_err(card->dev, "can't initialize aci\n");
1674+
return error;
1675+
}
1676+
error = snd_miro_restore_aci_state(miro);
1677+
if (error < 0)
1678+
return error;
1679+
1680+
miro->codec->resume(miro->codec);
1681+
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
1682+
return 0;
1683+
}
1684+
1685+
static int snd_miro_isa_suspend(struct device *dev, unsigned int n,
1686+
pm_message_t state)
1687+
{
1688+
return snd_miro_suspend(dev_get_drvdata(dev));
1689+
}
1690+
1691+
static int snd_miro_isa_resume(struct device *dev, unsigned int n)
1692+
{
1693+
return snd_miro_resume(dev_get_drvdata(dev));
1694+
}
1695+
#endif
1696+
14731697
#define DEV_NAME "miro"
14741698

14751699
static struct isa_driver snd_miro_driver = {
14761700
.match = snd_miro_isa_match,
14771701
.probe = snd_miro_isa_probe,
1478-
/* FIXME: suspend/resume */
1702+
#ifdef CONFIG_PM
1703+
.suspend = snd_miro_isa_suspend,
1704+
.resume = snd_miro_isa_resume,
1705+
#endif
14791706
.driver = {
14801707
.name = DEV_NAME
14811708
},
@@ -1591,12 +1818,29 @@ static void snd_miro_pnp_remove(struct pnp_card_link *pcard)
15911818
snd_miro_pnp_is_probed = 0;
15921819
}
15931820

1821+
#ifdef CONFIG_PM
1822+
static int snd_miro_pnp_suspend(struct pnp_card_link *pcard,
1823+
pm_message_t state)
1824+
{
1825+
return snd_miro_suspend(pnp_get_card_drvdata(pcard));
1826+
}
1827+
1828+
static int snd_miro_pnp_resume(struct pnp_card_link *pcard)
1829+
{
1830+
return snd_miro_resume(pnp_get_card_drvdata(pcard));
1831+
}
1832+
#endif
1833+
15941834
static struct pnp_card_driver miro_pnpc_driver = {
15951835
.flags = PNP_DRIVER_RES_DISABLE,
15961836
.name = "miro",
15971837
.id_table = snd_miro_pnpids,
15981838
.probe = snd_miro_pnp_probe,
15991839
.remove = snd_miro_pnp_remove,
1840+
#ifdef CONFIG_PM
1841+
.suspend = snd_miro_pnp_suspend,
1842+
.resume = snd_miro_pnp_resume,
1843+
#endif
16001844
};
16011845
#endif
16021846

0 commit comments

Comments
 (0)