Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 276558
b: refs/heads/master
c: f1a7374
h: refs/heads/master
v: v3
  • Loading branch information
Takashi Iwai committed Dec 6, 2011
1 parent 81a195b commit 430b851
Show file tree
Hide file tree
Showing 22 changed files with 655 additions and 268 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cce4aa378a049f4275416ee6302dd24f37b289df
refs/heads/master: f1a73746c6664442082e3d53e1804f46e1910436
81 changes: 23 additions & 58 deletions trunk/drivers/firmware/sigma.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,13 @@
#include <linux/module.h>
#include <linux/sigma.h>

static size_t sigma_action_size(struct sigma_action *sa)
{
size_t payload = 0;

switch (sa->instr) {
case SIGMA_ACTION_WRITEXBYTES:
case SIGMA_ACTION_WRITESINGLE:
case SIGMA_ACTION_WRITESAFELOAD:
payload = sigma_action_len(sa);
break;
default:
break;
}

payload = ALIGN(payload, 2);

return payload + sizeof(struct sigma_action);
}

/*
* Returns a negative error value in case of an error, 0 if processing of
* the firmware should be stopped after this action, 1 otherwise.
*/
/* Return: 0==OK, <0==error, =1 ==no more actions */
static int
process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw)
{
struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos);
size_t len = sigma_action_len(sa);
int ret;
int ret = 0;

pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
sa->instr, sa->addr, len);
Expand All @@ -50,50 +29,44 @@ process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
case SIGMA_ACTION_WRITEXBYTES:
case SIGMA_ACTION_WRITESINGLE:
case SIGMA_ACTION_WRITESAFELOAD:
if (ssfw->fw->size < ssfw->pos + len)
return -EINVAL;
ret = i2c_master_send(client, (void *)&sa->addr, len);
if (ret < 0)
return -EINVAL;
break;

case SIGMA_ACTION_DELAY:
ret = 0;
udelay(len);
len = 0;
break;

case SIGMA_ACTION_END:
return 0;
return 1;

default:
return -EINVAL;
}

return 1;
/* when arrive here ret=0 or sent data */
ssfw->pos += sigma_action_size(sa, len);
return ssfw->pos == ssfw->fw->size;
}

static int
process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
{
struct sigma_action *sa;
size_t size;
int ret;

while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);

size = sigma_action_size(sa);
ssfw->pos += size;
if (ssfw->pos > ssfw->fw->size || size == 0)
break;

ret = process_sigma_action(client, sa);
pr_debug("%s: processing %p\n", __func__, ssfw);

while (1) {
int ret = process_sigma_action(client, ssfw);
pr_debug("%s: action returned %i\n", __func__, ret);

if (ret <= 0)
if (ret == 1)
return 0;
else if (ret)
return ret;
}

if (ssfw->pos != ssfw->fw->size)
return -EINVAL;

return 0;
}

int process_sigma_firmware(struct i2c_client *client, const char *name)
Expand All @@ -116,24 +89,16 @@ int process_sigma_firmware(struct i2c_client *client, const char *name)

/* then verify the header */
ret = -EINVAL;

/*
* Reject too small or unreasonable large files. The upper limit has been
* chosen a bit arbitrarily, but it should be enough for all practical
* purposes and having the limit makes it easier to avoid integer
* overflows later in the loading process.
*/
if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)
if (fw->size < sizeof(*ssfw_head))
goto done;

ssfw_head = (void *)fw->data;
if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
goto done;

crc = crc32(0, fw->data + sizeof(*ssfw_head),
fw->size - sizeof(*ssfw_head));
crc = crc32(0, fw->data, fw->size);
pr_debug("%s: crc=%x\n", __func__, crc);
if (crc != le32_to_cpu(ssfw_head->crc))
if (crc != ssfw_head->crc)
goto done;

ssfw.pos = sizeof(*ssfw_head);
Expand Down
13 changes: 9 additions & 4 deletions trunk/include/linux/sigma.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct sigma_firmware {
struct sigma_firmware_header {
unsigned char magic[7];
u8 version;
__le32 crc;
u32 crc;
};

enum {
Expand All @@ -40,14 +40,19 @@ enum {
struct sigma_action {
u8 instr;
u8 len_hi;
__le16 len;
__be16 addr;
u16 len;
u16 addr;
unsigned char payload[];
};

static inline u32 sigma_action_len(struct sigma_action *sa)
{
return (sa->len_hi << 16) | le16_to_cpu(sa->len);
return (sa->len_hi << 16) | sa->len;
}

static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len)
{
return sizeof(*sa) + payload_len + (payload_len % 2);
}

extern int process_sigma_firmware(struct i2c_client *client, const char *name);
Expand Down
1 change: 1 addition & 0 deletions trunk/sound/pci/hda/hda_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -2508,6 +2508,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
Expand Down
2 changes: 1 addition & 1 deletion trunk/sound/pci/hda/patch_cirrus.c
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,7 @@ static const char * const cs420x_models[CS420X_MODELS] = {
[CS420X_MBP53] = "mbp53",
[CS420X_MBP55] = "mbp55",
[CS420X_IMAC27] = "imac27",
[CS420X_APPLE] = "apple",
[CS420X_IMAC27] = "apple",
[CS420X_AUTO] = "auto",
};

Expand Down
26 changes: 12 additions & 14 deletions trunk/sound/pci/hda/patch_realtek.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,12 +277,6 @@ static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
return false;
}

static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx)
{
return spec->capsrc_nids ?
spec->capsrc_nids[idx] : spec->adc_nids[idx];
}

/* select the given imux item; either unmute exclusively or select the route */
static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
unsigned int idx, bool force)
Expand All @@ -297,8 +291,6 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
imux = &spec->input_mux[mux_idx];
if (!imux->num_items && mux_idx > 0)
imux = &spec->input_mux[0];
if (!imux->num_items)
return 0;

if (idx >= imux->num_items)
idx = imux->num_items - 1;
Expand All @@ -311,7 +303,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
adc_idx = spec->dyn_adc_idx[idx];
}

nid = get_capsrc(spec, adc_idx);
nid = spec->capsrc_nids ?
spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];

/* no selection? */
num_conns = snd_hda_get_conn_list(codec, nid, NULL);
Expand Down Expand Up @@ -1065,7 +1058,8 @@ static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
hda_nid_t pin = spec->imux_pins[i];
int c;
for (c = 0; c < spec->num_adc_nids; c++) {
hda_nid_t cap = get_capsrc(spec, c);
hda_nid_t cap = spec->capsrc_nids ?
spec->capsrc_nids[c] : spec->adc_nids[c];
int idx = get_connection_index(codec, cap, pin);
if (idx >= 0) {
imux->items[i].index = idx;
Expand Down Expand Up @@ -1975,8 +1969,10 @@ static int alc_build_controls(struct hda_codec *codec)
if (!kctl)
kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
for (i = 0; kctl && i < kctl->count; i++) {
err = snd_hda_add_nid(codec, kctl, i,
get_capsrc(spec, i));
const hda_nid_t *nids = spec->capsrc_nids;
if (!nids)
nids = spec->adc_nids;
err = snd_hda_add_nid(codec, kctl, i, nids[i]);
if (err < 0)
return err;
}
Expand Down Expand Up @@ -2763,7 +2759,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
}

for (c = 0; c < num_adcs; c++) {
hda_nid_t cap = get_capsrc(spec, c);
hda_nid_t cap = spec->capsrc_nids ?
spec->capsrc_nids[c] : spec->adc_nids[c];
idx = get_connection_index(codec, cap, pin);
if (idx >= 0) {
spec->imux_pins[imux->num_items] = pin;
Expand Down Expand Up @@ -3709,7 +3706,8 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
if (!pin)
return 0;
for (i = 0; i < spec->num_adc_nids; i++) {
hda_nid_t cap = get_capsrc(spec, i);
hda_nid_t cap = spec->capsrc_nids ?
spec->capsrc_nids[i] : spec->adc_nids[i];
int idx;

idx = get_connection_index(codec, cap, pin);
Expand Down
Loading

0 comments on commit 430b851

Please sign in to comment.