>From 63adc7c2da712b609deaad14a03f7e88dcaa571b Mon Sep 17 00:00:00 2001 From: R Dharageswari <[email protected]> Date: Tue, 7 Dec 2010 17:43:39 +0530 Subject: [PATCH 4/4] sst:lineout implementation in audio driver
This patch adds the support for MFLD lineout. This lineout input can be selected as any input channel by using a new alsa mixer kcontrol. Signed-off-by: R Dharageswari <[email protected]> Signed-off-by: Ramesh Babu K V <[email protected]> --- include/sound/intel_sst.h | 6 +- sound/pci/sst/intelmid.c | 3 +- sound/pci/sst/intelmid.h | 1 + sound/pci/sst/intelmid_ctrl.c | 22 +++- sound/pci/sst/intelmid_msic_control.c | 254 +++++++++++++++++++++++++++++++-- sound/pci/sst/intelmid_snd_control.h | 7 + sound/pci/sst/intelmid_v0_control.c | 6 +- sound/pci/sst/intelmid_v1_control.c | 5 + sound/pci/sst/intelmid_v2_control.c | 6 +- 9 files changed, 292 insertions(+), 18 deletions(-) diff --git a/include/sound/intel_sst.h b/include/sound/intel_sst.h index d2d3653..bb1ea30 100644 --- a/include/sound/intel_sst.h +++ b/include/sound/intel_sst.h @@ -83,12 +83,14 @@ struct snd_pmic_ops { int num_channel; int input_dev_id; int mute_status; - int pb_on; + int pb_on, pbhs_on; int cap_on; int output_dev_id; + int lineout_dev_id, line_out_names_cnt; + int prev_lineout_dev_id; int (*set_input_dev) (u8 value); int (*set_output_dev) (u8 value); - + int (*set_lineout_dev) (u8 value); int (*set_mute) (int dev_id, u8 value); int (*get_mute) (int dev_id, u8 *value); diff --git a/sound/pci/sst/intelmid.c b/sound/pci/sst/intelmid.c index 44431d7..c5cbeb6 100644 --- a/sound/pci/sst/intelmid.c +++ b/sound/pci/sst/intelmid.c @@ -180,7 +180,7 @@ static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream) return ret_val; } - ret_val = snd_intelmad_alloc_stream(substream); + ret_val = snd_intelmad_alloc_stream(substream); if (ret_val < 0) return ret_val; stream->dbg_cum_bytes = 0; @@ -803,6 +803,7 @@ static int __devinit snd_intelmad_sst_register( intelmaddata->sstdrv_ops->scard_ops->input_dev_id = DMIC; intelmaddata->sstdrv_ops->scard_ops->output_dev_id = STEREO_HEADPHONE; + intelmaddata->sstdrv_ops->scard_ops->lineout_dev_id = NONE; } /* registering with SST driver to get access to SST APIs to use */ diff --git a/sound/pci/sst/intelmid.h b/sound/pci/sst/intelmid.h index 9f1790a..26f144e 100644 --- a/sound/pci/sst/intelmid.h +++ b/sound/pci/sst/intelmid.h @@ -116,6 +116,7 @@ struct snd_intelmad { void __iomem *int_base; int output_sel; int input_sel; + int lineout_sel; int master_mute; struct mad_jack jack[4]; int playback_cnt; diff --git a/sound/pci/sst/intelmid_ctrl.c b/sound/pci/sst/intelmid_ctrl.c index e996474..d3e3ff0 100644 --- a/sound/pci/sst/intelmid_ctrl.c +++ b/sound/pci/sst/intelmid_ctrl.c @@ -36,6 +36,11 @@ static char *out_names_mrst[] = {"Headphones", static char *in_names_mrst[] = {"AMIC", "DMIC", "HS_MIC"}; +static char *line_out_names_mfld[] = {"Headset", + "IHF ", + "Vibra1 ", + "Vibra2 ", + "NONE "}; static char *vmic_names_mfld[] = {"IHF-left ", "IHF-right ", "Headset-Left ", @@ -195,7 +200,10 @@ static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol, uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mfld); else if (kcontrol->id.numid == INPUT_SEL) uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mfld); - else if (kcontrol->id.numid == VMIC_SEL_MFLD) + else if (kcontrol->id.numid == LINEOUT_SEL_MFLD) { + uinfo->value.enumerated.items = ARRAY_SIZE(line_out_names_mfld); + scard_ops->line_out_names_cnt = uinfo->value.enumerated.items; + } else if (kcontrol->id.numid == VMIC_SEL_MFLD) uinfo->value.enumerated.items = ARRAY_SIZE(vmic_names_mfld); else return -EINVAL; @@ -212,6 +220,10 @@ static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol, strncpy(uinfo->value.enumerated.name, in_names_mfld[uinfo->value.enumerated.item], sizeof(uinfo->value.enumerated.name)-1); + else if (kcontrol->id.numid == LINEOUT_SEL_MFLD) + strncpy(uinfo->value.enumerated.name, + line_out_names_mfld[uinfo->value.enumerated.item], + sizeof(uinfo->value.enumerated.name)-1); else if (kcontrol->id.numid == VMIC_SEL_MFLD) strncpy(uinfo->value.enumerated.name, vmic_names_mfld[uinfo->value.enumerated.item], @@ -491,6 +503,9 @@ static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol, else if (kcontrol->id.numid == INPUT_SEL) uval->value.enumerated.item[0] = scard_ops->input_dev_id; + else if (kcontrol->id.numid == LINEOUT_SEL_MFLD) + uval->value.enumerated.item[0] = + scard_ops->lineout_dev_id; else if (kcontrol->id.numid == VMIC_SEL_MFLD) uval->value.enumerated.item[0] = kcontrol->private_value; @@ -557,6 +572,11 @@ static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol, uval->value.enumerated.item[0]); intelmaddata->input_sel = uval->value.enumerated.item[0]; break; + case LINEOUT_SEL_MFLD: + ret_val = scard_ops->set_lineout_dev( + uval->value.enumerated.item[0]); + intelmaddata->lineout_sel = uval->value.enumerated.item[0]; + break; case VMIC_SEL_MFLD: pcm_control = intelmaddata->sstdrv_ops->pcm_control; if (uval->value.enumerated.item[0] == IHFL) diff --git a/sound/pci/sst/intelmid_msic_control.c b/sound/pci/sst/intelmid_msic_control.c index 37524bb..de07fec 100644 --- a/sound/pci/sst/intelmid_msic_control.c +++ b/sound/pci/sst/intelmid_msic_control.c @@ -51,11 +51,8 @@ static int msic_init_card(void) /*TI vibra w/a settings*/ {0x384, 0x80, 0}, {0x385, 0x80, 0}, - /*vibra settings*/ {0x267, 0x00, 0}, - {0x26A, 0x10, 0}, {0x261, 0x00, 0}, - {0x264, 0x10, 0}, /* pcm port setting */ {0x278, 0x00, 0}, {0x27B, 0x01, 0}, @@ -77,14 +74,221 @@ static int msic_init_card(void) {0x1e, 0x00, 0x00}, }; snd_msic_ops.card_status = SND_CARD_INIT_DONE; - sst_sc_reg_access(sc_access, PMIC_WRITE, 30); + sst_sc_reg_access(sc_access, PMIC_WRITE, 28); snd_msic_ops.pb_on = 0; + snd_msic_ops.pbhs_on = 0; snd_msic_ops.cap_on = 0; snd_msic_ops.input_dev_id = DMIC; /*def dev*/ snd_msic_ops.output_dev_id = STEREO_HEADPHONE; pr_debug("sst: msic init complete!!\n"); return 0; } +static int msic_line_out_restore(u8 value) +{ + struct sc_reg_access hs_drv_en[] = { + {0x25d, 0x03, 0x03}, + }; + struct sc_reg_access ep_drv_en[] = { + {0x25d, 0x40, 0x40}, + }; + struct sc_reg_access ihf_drv_en[] = { + {0x25d, 0x0c, 0x0c}, + }; + struct sc_reg_access vib1_drv_en[] = { + {0x25d, 0x10, 0x10}, + }; + struct sc_reg_access vib2_drv_en[] = { + {0x25d, 0x20, 0x20}, + }; + int retval = 0; + + pr_debug("sst: msic_lineout_restore_lineout_dev:%d\n", value); + + switch (value) { + case HEADSET: + pr_debug("sst: Selecting Lineout-HEADSET-restore\n"); + if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE) + retval = sst_sc_reg_access(hs_drv_en, + PMIC_READ_MODIFY, 1); + else + retval = sst_sc_reg_access(ep_drv_en, + PMIC_READ_MODIFY, 1); + break; + case IHF: + pr_debug("sst: Selecting Lineout-IHF-restore\n"); + retval = sst_sc_reg_access(ihf_drv_en, PMIC_READ_MODIFY, 1); + break; + case VIBRA1: + pr_debug("sst: Selecting Lineout-Vibra1-restore\n"); + retval = sst_sc_reg_access(vib1_drv_en, PMIC_READ_MODIFY, 1); + break; + case VIBRA2: + pr_debug("sst: Selecting Lineout-VIBRA2-restore\n"); + retval = sst_sc_reg_access(vib2_drv_en, PMIC_READ_MODIFY, 1); + break; + case NONE: + pr_debug("sst: Selecting Lineout-NONE-restore\n"); + break; + default: + return -EINVAL; + } + return retval; +} +static int msic_get_lineout_prvstate(void) +{ + struct sc_reg_access hs_ihf_drv[2] = { + {0x257, 0x0, 0x0}, + {0x25d, 0x0, 0x0}, + }; + struct sc_reg_access vib1drv[2] = { + {0x264, 0x0, 0x0}, + {0x25D, 0x0, 0x0}, + }; + struct sc_reg_access vib2drv[2] = { + {0x26A, 0x0, 0x0}, + {0x25D, 0x0, 0x0}, + }; + int retval = 0, drv_en, dac_en, dev_id, mask; + for (dev_id = 0; dev_id < snd_msic_ops.line_out_names_cnt; dev_id++) { + switch (dev_id) { + case HEADSET: + pr_debug("sst: msic_get_lineout_prvs_state: HEADSET\n"); + sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2); + + mask = (MASK0|MASK1); + dac_en = (hs_ihf_drv[0].value) & mask; + + mask = ((MASK0|MASK1)|MASK6); + drv_en = (hs_ihf_drv[1].value) & mask; + + if (dac_en && (!drv_en)) { + snd_msic_ops.prev_lineout_dev_id = HEADSET; + return retval; + } + break; + case IHF: + pr_debug("sst: msic_get_lineout_prvstate: IHF\n"); + sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2); + + mask = (MASK2 | MASK3); + dac_en = (hs_ihf_drv[0].value) & mask; + + mask = (MASK2 | MASK3); + drv_en = (hs_ihf_drv[1].value) & mask; + + if (dac_en && (!drv_en)) { + snd_msic_ops.prev_lineout_dev_id = IHF; + return retval; + } + break; + case VIBRA1: + pr_debug("sst: msic_get_lineout_prvstate: vibra1\n"); + sst_sc_reg_access(vib1drv, PMIC_READ, 2); + + mask = MASK1; + dac_en = (vib1drv[0].value) & mask; + + mask = MASK4; + drv_en = (vib1drv[1].value) & mask; + + if (dac_en && (!drv_en)) { + snd_msic_ops.prev_lineout_dev_id = VIBRA1; + return retval; + } + break; + case VIBRA2: + pr_debug("sst: msic_get_lineout_prvstate: vibra2\n"); + sst_sc_reg_access(vib2drv, PMIC_READ, 2); + + mask = MASK1; + dac_en = (vib2drv[0].value) & mask; + + mask = MASK5; + drv_en = ((vib2drv[1].value) & mask); + + if (dac_en && (!drv_en)) { + snd_msic_ops.prev_lineout_dev_id = VIBRA2; + return retval; + } + break; + case NONE: + pr_debug("sst: msic_get_lineout_prvstate: NONE\n"); + snd_msic_ops.prev_lineout_dev_id = NONE; + return retval; + default: + pr_debug("sst: Invalid device id\n"); + snd_msic_ops.prev_lineout_dev_id = NONE; + return -EINVAL; + } + } + return retval; +} +static int msic_set_selected_lineout_dev(u8 value) +{ + struct sc_reg_access lout_hs[] = { + {0x25e, 0x33, 0xFF}, + {0x25d, 0x0, 0x43}, + }; + struct sc_reg_access lout_ihf[] = { + {0x25e, 0x55, 0xff}, + {0x25d, 0x0, 0x0c}, + }; + struct sc_reg_access lout_vibra1[] = { + + {0x25e, 0x61, 0xff}, + {0x25d, 0x0, 0x10}, + }; + struct sc_reg_access lout_vibra2[] = { + + {0x25e, 0x16, 0xff}, + {0x25d, 0x0, 0x20}, + }; + struct sc_reg_access lout_def[] = { + {0x25e, 0x66, 0x0}, + }; + int retval = 0; + + pr_debug("sst: msic_set_selected_lineout_dev:%d\n", value); + msic_get_lineout_prvstate(); + msic_line_out_restore(snd_msic_ops.prev_lineout_dev_id); + snd_msic_ops.lineout_dev_id = value; + + switch (value) { + case HEADSET: + pr_debug("sst: Selecting Lineout-HEADSET\n"); + if (snd_msic_ops.pb_on) + retval = sst_sc_reg_access(lout_hs, + PMIC_READ_MODIFY, 2); + break; + case IHF: + pr_debug("sst: Selecting Lineout-IHF\n"); + if (snd_msic_ops.pb_on) + retval = sst_sc_reg_access(lout_ihf, + PMIC_READ_MODIFY, 2); + break; + case VIBRA1: + pr_debug("sst: Selecting Lineout-Vibra1\n"); + if (snd_msic_ops.pb_on) + retval = sst_sc_reg_access(lout_vibra1, + PMIC_READ_MODIFY, 2); + break; + case VIBRA2: + pr_debug("sst: Selecting Lineout-VIBRA2\n"); + if (snd_msic_ops.pb_on) + retval = sst_sc_reg_access(lout_vibra2, + PMIC_READ_MODIFY, 2); + break; + case NONE: + pr_debug("sst: Selecting Lineout-NONE\n"); + retval = sst_sc_reg_access(lout_def, + PMIC_WRITE, 1); + break; + default: + return -EINVAL; + } + return retval; +} + static int msic_power_up_pb(unsigned int device) { @@ -158,12 +362,12 @@ static int msic_power_up_pb(unsigned int device) struct sc_reg_access vib1_en[] = { /* enable driver, ADC */ {0x25D, 0x10, 0x10}, - {0x264, 0x02, 0x02}, + {0x264, 0x02, 0x82}, }; struct sc_reg_access vib2_en[] = { /* enable driver, ADC */ {0x25D, 0x20, 0x20}, - {0x26A, 0x02, 0x02}, + {0x26A, 0x02, 0x82}, }; struct sc_reg_access pcm2_en[] = { /* enable pcm 2 */ @@ -184,6 +388,8 @@ static int msic_power_up_pb(unsigned int device) msleep(1); switch (device) { case SND_SST_DEVICE_HEADSET: + snd_msic_ops.pb_on = 1; + snd_msic_ops.pbhs_on = 1; if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE) { sst_sc_reg_access(vhs, PMIC_WRITE, 2); sst_sc_reg_access(hsdac, PMIC_READ_MODIFY, 2); @@ -194,22 +400,31 @@ static int msic_power_up_pb(unsigned int device) sst_sc_reg_access(hs_filter, PMIC_WRITE, 2); sst_sc_reg_access(ep_enable, PMIC_READ_MODIFY, 3); } - snd_msic_ops.pb_on = 1; + if (snd_msic_ops.lineout_dev_id == HEADSET) + msic_set_selected_lineout_dev(HEADSET); break; - case SND_SST_DEVICE_IHF: + snd_msic_ops.pb_on = 1; sst_sc_reg_access(vihf, PMIC_WRITE, 1); sst_sc_reg_access(ihf_filter, PMIC_READ_MODIFY, 3); sst_sc_reg_access(ihf_en, PMIC_READ_MODIFY, 1); sst_sc_reg_access(ihf_unmute, PMIC_READ_MODIFY, 2); + if (snd_msic_ops.lineout_dev_id == IHF) + msic_set_selected_lineout_dev(IHF); break; case SND_SST_DEVICE_VIBRA: + snd_msic_ops.pb_on = 1; sst_sc_reg_access(vib1_en, PMIC_READ_MODIFY, 2); + if (snd_msic_ops.lineout_dev_id == VIBRA1) + msic_set_selected_lineout_dev(VIBRA1); break; case SND_SST_DEVICE_HAPTIC: + snd_msic_ops.pb_on = 1; sst_sc_reg_access(vib2_en, PMIC_READ_MODIFY, 2); + if (snd_msic_ops.lineout_dev_id == VIBRA2) + msic_set_selected_lineout_dev(VIBRA2); break; default: @@ -307,6 +522,7 @@ static int msic_power_down(void) }; pr_debug("sst: powering dn msic\n"); + snd_msic_ops.pbhs_on = 0; snd_msic_ops.pb_on = 0; snd_msic_ops.cap_on = 0; sst_sc_reg_access(power_dn, PMIC_WRITE, 3); @@ -345,15 +561,22 @@ static int msic_power_down_pb(unsigned int device) struct sc_reg_access vib2_off[] = { {0x26A, 0x00, 0x82}, }; + struct sc_reg_access lout_off[] = { + {0x25e, 0x66, 0x00}, + }; + + pr_debug("sst: powering dn pb for device %d\n", device); switch (device) { case SND_SST_DEVICE_HEADSET: - snd_msic_ops.pb_on = 0; + snd_msic_ops.pbhs_on = 0; sst_sc_reg_access(hs_mute, PMIC_READ_MODIFY, 3); drv_enable[0].mask = 0x43; sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1); sst_sc_reg_access(hs_off, PMIC_READ_MODIFY, 2); + if (snd_msic_ops.lineout_dev_id == HEADSET) + sst_sc_reg_access(lout_off, PMIC_WRITE, 1); break; case SND_SST_DEVICE_IHF: @@ -361,18 +584,24 @@ static int msic_power_down_pb(unsigned int device) drv_enable[0].mask = 0x0C; sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1); sst_sc_reg_access(ihf_off, PMIC_READ_MODIFY, 2); + if (snd_msic_ops.lineout_dev_id == IHF) + sst_sc_reg_access(lout_off, PMIC_WRITE, 1); break; case SND_SST_DEVICE_VIBRA: - sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 2); + sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 1); drv_enable[0].mask = 0x10; sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1); + if (snd_msic_ops.lineout_dev_id == VIBRA1) + sst_sc_reg_access(lout_off, PMIC_WRITE, 1); break; case SND_SST_DEVICE_HAPTIC: - sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 2); + sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 1); drv_enable[0].mask = 0x20; sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1); + if (snd_msic_ops.lineout_dev_id == VIBRA2) + sst_sc_reg_access(lout_off, PMIC_WRITE, 1); break; } return 0; @@ -411,7 +640,7 @@ static int msic_set_selected_output_dev(u8 value) pr_debug("sst: msic set selected output:%d\n", value); snd_msic_ops.output_dev_id = value; - if (snd_msic_ops.pb_on) + if (snd_msic_ops.pbhs_on) msic_power_up_pb(SND_SST_DEVICE_HEADSET); return retval; } @@ -491,6 +720,7 @@ static int msic_get_vol(int dev_id, int *value) struct snd_pmic_ops snd_msic_ops = { .set_input_dev = msic_set_selected_input_dev, .set_output_dev = msic_set_selected_output_dev, + .set_lineout_dev = msic_set_selected_lineout_dev, .set_mute = msic_set_mute, .get_mute = msic_get_mute, .set_vol = msic_set_vol, diff --git a/sound/pci/sst/intelmid_snd_control.h b/sound/pci/sst/intelmid_snd_control.h index a4565f3..c7e9f16 100644 --- a/sound/pci/sst/intelmid_snd_control.h +++ b/sound/pci/sst/intelmid_snd_control.h @@ -80,6 +80,13 @@ enum SND_INPUT_DEVICE { HS_MIC, IN_UNDEFINED }; +enum SND_LINE_OUT_DEVICE { + HEADSET, + IHF, + VIBRA1, + VIBRA2, + NONE, +}; enum SND_OUTPUT_DEVICE { STEREO_HEADPHONE, diff --git a/sound/pci/sst/intelmid_v0_control.c b/sound/pci/sst/intelmid_v0_control.c index 00241fa..41cb468 100644 --- a/sound/pci/sst/intelmid_v0_control.c +++ b/sound/pci/sst/intelmid_v0_control.c @@ -492,7 +492,10 @@ static int fs_set_selected_output_dev(u8 value) } } - +static int fs_set_selected_lineout_dev(u8 value) +{ + return 0; +} static int fs_set_mute(int dev_id, u8 value) { struct sc_reg_access sc_access[6] = {{0,},}; @@ -754,6 +757,7 @@ static int fs_get_vol(int dev_id, int *value) struct snd_pmic_ops snd_pmic_ops_fs = { .set_input_dev = fs_set_selected_input_dev, .set_output_dev = fs_set_selected_output_dev, + .set_lineout_dev = fs_set_selected_lineout_dev, .set_mute = fs_set_mute, .get_mute = fs_get_mute, .set_vol = fs_set_vol, diff --git a/sound/pci/sst/intelmid_v1_control.c b/sound/pci/sst/intelmid_v1_control.c index 959b218..75d7a6e 100644 --- a/sound/pci/sst/intelmid_v1_control.c +++ b/sound/pci/sst/intelmid_v1_control.c @@ -795,6 +795,10 @@ static int mx_set_selected_input_dev(u8 dev_id) } return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg); } +static int mx_set_selected_lineout_dev(u8 dev_id) +{ + return 0; +} static int mx_set_mute(int dev_id, u8 value) { @@ -1045,6 +1049,7 @@ static int mx_get_vol(int dev_id, int *value) struct snd_pmic_ops snd_pmic_ops_mx = { .set_input_dev = mx_set_selected_input_dev, .set_output_dev = mx_set_selected_output_dev, + .set_lineout_dev = mx_set_selected_lineout_dev, .set_mute = mx_set_mute, .get_mute = mx_get_mute, .set_vol = mx_set_vol, diff --git a/sound/pci/sst/intelmid_v2_control.c b/sound/pci/sst/intelmid_v2_control.c index 367f956..4214e30 100644 --- a/sound/pci/sst/intelmid_v2_control.c +++ b/sound/pci/sst/intelmid_v2_control.c @@ -882,7 +882,10 @@ static int nc_set_selected_input_dev(u8 value) } return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_val); } - +static int nc_set_selected_lineout_dev(u8 dev_id) +{ + return 0; +} static int nc_get_mute(int dev_id, u8 *value) { int retval = 0, mask = 0; @@ -987,6 +990,7 @@ static int nc_get_vol(int dev_id, int *value) struct snd_pmic_ops snd_pmic_ops_nc = { .set_input_dev = nc_set_selected_input_dev, .set_output_dev = nc_set_selected_output_dev, + .set_lineout_dev = nc_set_selected_lineout_dev, .set_mute = nc_set_mute, .get_mute = nc_get_mute, .set_vol = nc_set_vol, -- 1.6.2.5
0004-sst-lineout-implementation-in-audio-driver.patch
Description: 0004-sst-lineout-implementation-in-audio-driver.patch
_______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
