LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 003/003] snd-powermac: Burgundy mixers for B&W and iMac
From: Risto Suominen @ 2008-04-07 13:29 UTC (permalink / raw)
  To: perex; +Cc: LinuxPPC-dev

From: Risto Suominen <Risto.Suominen@gmail.com>

Add mixer controls and correct headphone detection bits for PowerMac
G3 B&W and iMac G3 Tray-loading, both having Burgundy chipset.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
---
Kernel version 2.6.25-rc8 (probably any 2.6)

--- sound/ppc/burgundy.c.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/burgundy.c	2008-04-07 12:00:20.893307568 +0300
@@ -102,7 +102,8 @@ snd_pmac_burgundy_rcw(struct snd_pmac *c
 }

 static void
-snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr,
unsigned int val)
+snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr,
+		      unsigned int val)
 {
 	out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
 	snd_pmac_burgundy_busy_wait(chip);
@@ -126,8 +127,11 @@ snd_pmac_burgundy_rcb(struct snd_pmac *c
 	return val;
 }

+#define BASE2ADDR(base)	((base) << 12)
+#define ADDR2BASE(addr)	((addr) >> 12)
+
 /*
- * Burgundy volume: 0 - 100, stereo
+ * Burgundy volume: 0 - 100, stereo, word reg
  */
 static void
 snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
@@ -168,13 +172,6 @@ snd_pmac_burgundy_read_volume(struct snd
 		volume[1] = 0;
 }

-
-/*
- */
-
-#define BASE2ADDR(base)	((base) << 12)
-#define ADDR2BASE(addr)	((addr) >> 12)
-
 static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_info *uinfo)
 {
@@ -191,8 +188,8 @@ static int snd_pmac_burgundy_get_volume(
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
 	int shift = (kcontrol->private_value >> 8) & 0xff;
-	snd_pmac_burgundy_read_volume(chip, addr, ucontrol->value.integer.value,
-				      shift);
+	snd_pmac_burgundy_read_volume(chip, addr,
+				      ucontrol->value.integer.value, shift);
 	return 0;
 }

@@ -204,24 +201,163 @@ static int snd_pmac_burgundy_put_volume(
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	long nvoices[2];

-	snd_pmac_burgundy_write_volume(chip, addr, ucontrol->value.integer.value,
-				       shift);
+	snd_pmac_burgundy_write_volume(chip, addr,
+				       ucontrol->value.integer.value, shift);
 	snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift);
 	return (nvoices[0] != ucontrol->value.integer.value[0] ||
 		nvoices[1] != ucontrol->value.integer.value[1]);
 }

-#define BURGUNDY_VOLUME(xname, xindex, addr, shift) \
+#define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
   .info = snd_pmac_burgundy_info_volume,\
   .get = snd_pmac_burgundy_get_volume,\
   .put = snd_pmac_burgundy_put_volume,\
   .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) }

-/* lineout/speaker */
+/*
+ * Burgundy volume: 0 - 100, stereo, 2-byte reg
+ */
+static void
+snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address,
+				  long *volume, int off)
+{
+	int lvolume, rvolume;
+
+	off |= off << 2;
+	lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
+	rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
+
+	snd_pmac_burgundy_wcb(chip, address + off, lvolume);
+	snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume);
+}
+
+static void
+snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address,
+				 long *volume, int off)
+{
+	volume[0] = snd_pmac_burgundy_rcb(chip, address + off);
+	if (volume[0] >= BURGUNDY_VOLUME_OFFSET)
+		volume[0] -= BURGUNDY_VOLUME_OFFSET;
+	else
+		volume[0] = 0;
+	volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100);
+	if (volume[1] >= BURGUNDY_VOLUME_OFFSET)
+		volume[1] -= BURGUNDY_VOLUME_OFFSET;
+	else
+		volume[1] = 0;
+}
+
+static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 100;
+	return 0;
+}
+
+static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int off = kcontrol->private_value & 0x300;
+	snd_pmac_burgundy_read_volume_2b(chip, addr,
+			ucontrol->value.integer.value, off);
+	return 0;
+}
+
+static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int off = kcontrol->private_value & 0x300;
+	long nvoices[2];
+
+	snd_pmac_burgundy_write_volume_2b(chip, addr,
+			ucontrol->value.integer.value, off);
+	snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off);
+	return (nvoices[0] != ucontrol->value.integer.value[0] ||
+		nvoices[1] != ucontrol->value.integer.value[1]);
+}
+
+#define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+  .info = snd_pmac_burgundy_info_volume_2b,\
+  .get = snd_pmac_burgundy_get_volume_2b,\
+  .put = snd_pmac_burgundy_put_volume_2b,\
+  .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) }
+
+/*
+ * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg
+ */
+static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_info *uinfo)
+{
+	int stereo = (kcontrol->private_value >> 24) & 1;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = stereo + 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 15;
+	return 0;
+}
+
+static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int stereo = (kcontrol->private_value >> 24) & 1;
+	int atten = (kcontrol->private_value >> 25) & 1;
+	int oval;
+
+	oval = snd_pmac_burgundy_rcb(chip, addr);
+	if (atten)
+		oval = ~oval & 0xff;
+	ucontrol->value.integer.value[0] = oval & 0xf;
+	if (stereo)
+		ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
+	return 0;
+}

-static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
-					     struct snd_ctl_elem_info *uinfo)
+static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int stereo = (kcontrol->private_value >> 24) & 1;
+	int atten = (kcontrol->private_value >> 25) & 1;
+	int oval, val;
+
+	oval = snd_pmac_burgundy_rcb(chip, addr);
+	if (atten)
+		oval = ~oval & 0xff;
+	val = ucontrol->value.integer.value[0];
+	if (stereo)
+		val |= ucontrol->value.integer.value[1] << 4;
+	else
+		val |= ucontrol->value.integer.value[0] << 4;
+	if (atten)
+		val = ~val & 0xff;
+	snd_pmac_burgundy_wcb(chip, addr, val);
+	return val != oval;
+}
+
+#define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+  .info = snd_pmac_burgundy_info_gain,\
+  .get = snd_pmac_burgundy_get_gain,\
+  .put = snd_pmac_burgundy_put_gain,\
+  .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) }
+
+/*
+ * Burgundy switch: 0/1, mono/stereo, word reg
+ */
+static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_info *uinfo)
 {
 	int stereo = (kcontrol->private_value >> 24) & 1;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -231,111 +367,207 @@ static int snd_pmac_burgundy_info_switch
 	return 0;
 }

-static int snd_pmac_burgundy_get_switch_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int lmask = kcontrol->private_value & 0xff;
-	int rmask = (kcontrol->private_value >> 8) & 0xff;
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = 1 << (kcontrol->private_value & 0xff);
+	int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	int val = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+	int val = snd_pmac_burgundy_rcw(chip, addr);
 	ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
 	if (stereo)
 		ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
 	return 0;
 }

-static int snd_pmac_burgundy_put_switch_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int lmask = kcontrol->private_value & 0xff;
-	int rmask = (kcontrol->private_value >> 8) & 0xff;
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = 1 << (kcontrol->private_value & 0xff);
+	int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
 	int stereo = (kcontrol->private_value >> 24) & 1;
 	int val, oval;
-	oval = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
-	val = oval & ~(lmask | rmask);
+	oval = snd_pmac_burgundy_rcw(chip, addr);
+	val = oval & ~(lmask | (stereo ? rmask : 0));
 	if (ucontrol->value.integer.value[0])
 		val |= lmask;
 	if (stereo && ucontrol->value.integer.value[1])
 		val |= rmask;
-	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, val);
+	snd_pmac_burgundy_wcw(chip, addr, val);
 	return val != oval;
 }

-#define BURGUNDY_OUTPUT_SWITCH(xname, xindex, lmask, rmask, stereo) \
+#define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
-  .info = snd_pmac_burgundy_info_switch_out,\
-  .get = snd_pmac_burgundy_get_switch_out,\
-  .put = snd_pmac_burgundy_put_switch_out,\
-  .private_value = ((lmask) | ((rmask) << 8) | ((stereo) << 24)) }
-
-/* line/speaker output volume */
-static int snd_pmac_burgundy_info_volume_out(struct snd_kcontrol *kcontrol,
-					     struct snd_ctl_elem_info *uinfo)
+  .info = snd_pmac_burgundy_info_switch_w,\
+  .get = snd_pmac_burgundy_get_switch_w,\
+  .put = snd_pmac_burgundy_put_switch_w,\
+  .private_value = ((lbit) | ((rbit) << 8)\
+		| (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
+
+/*
+ * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask
+ */
+static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_info *uinfo)
 {
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = stereo + 1;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 15;
+	uinfo->value.integer.max = 1;
 	return 0;
 }

-static int snd_pmac_burgundy_get_volume_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = kcontrol->private_value & 0xff;
+	int rmask = (kcontrol->private_value >> 8) & 0xff;
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	int oval;
-
-	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
-	ucontrol->value.integer.value[0] = oval & 0xf;
+	int val = snd_pmac_burgundy_rcb(chip, addr);
+	ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
 	if (stereo)
-		ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
+		ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
 	return 0;
 }

-static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = kcontrol->private_value & 0xff;
+	int rmask = (kcontrol->private_value >> 8) & 0xff;
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	unsigned int oval, val;
-
-	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
-	val = ucontrol->value.integer.value[0] & 15;
-	if (stereo)
-		val |= (ucontrol->value.integer.value[1] & 15) << 4;
-	else
-		val |= val << 4;
-	val = ~val & 0xff;
+	int val, oval;
+	oval = snd_pmac_burgundy_rcb(chip, addr);
+	val = oval & ~(lmask | rmask);
+	if (ucontrol->value.integer.value[0])
+		val |= lmask;
+	if (stereo && ucontrol->value.integer.value[1])
+		val |= rmask;
 	snd_pmac_burgundy_wcb(chip, addr, val);
 	return val != oval;
 }

-#define BURGUNDY_OUTPUT_VOLUME(xname, xindex, addr, stereo) \
+#define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
-  .info = snd_pmac_burgundy_info_volume_out,\
-  .get = snd_pmac_burgundy_get_volume_out,\
-  .put = snd_pmac_burgundy_put_volume_out,\
-  .private_value = (ADDR2BASE(addr) | ((stereo) << 24)) }
+  .info = snd_pmac_burgundy_info_switch_b,\
+  .get = snd_pmac_burgundy_get_switch_b,\
+  .put = snd_pmac_burgundy_put_switch_b,\
+  .private_value = ((lmask) | ((rmask) << 8)\
+		| (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }

+/*
+ * Burgundy mixers
+ */
 static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __initdata = {
-	BURGUNDY_VOLUME("Master Playback Volume", 0,
MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
-	BURGUNDY_VOLUME("Line Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLLINE, 16),
-	BURGUNDY_VOLUME("CD Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLCD, 16),
-	BURGUNDY_VOLUME("Mic Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLMIC, 16),
-	BURGUNDY_OUTPUT_VOLUME("PC Speaker Playback Volume", 0,
MASK_ADDR_BURGUNDY_ATTENHP, 0),
-	/*BURGUNDY_OUTPUT_VOLUME("PCM Playback Volume", 0,
MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1),*/
-	BURGUNDY_OUTPUT_VOLUME("Headphone Playback Volume", 0,
MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1),
-};	
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw __initdata =
-BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0,
BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw __initdata =
-BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0,
BURGUNDY_OUTPUT_INTERN, 0, 0);
+	BURGUNDY_VOLUME_W("Master Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
+	BURGUNDY_VOLUME_W("CD Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLCD, 16),
+	BURGUNDY_VOLUME_2B("Input Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIX01, 2),
+	BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIX23, 0),
+	BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINCD, 1, 0),
+	BURGUNDY_SWITCH_W("Master Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0),
+	BURGUNDY_SWITCH_W("CD Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1),
+	BURGUNDY_SWITCH_W("CD Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1),
+/*	BURGUNDY_SWITCH_W("Loop Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1),
+ *	BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0),
+ *	BURGUNDY_SWITCH_B("Mixer Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0),
+ *	BURGUNDY_SWITCH_B("PCM out Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0),
+ */	BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __initdata = {
+	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLLINE, 16),
+	BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIC, 16),
+	BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINLINE, 1, 0),
+	BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
+	BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
+	BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1),
+	BURGUNDY_VOLUME_B("Headphone Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENHP, 1, 1),
+	BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1),
+	BURGUNDY_SWITCH_W("Mic Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
+	BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1),
+	BURGUNDY_SWITCH_W("Mic Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
+	BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __initdata = {
+	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIC, 16),
+	BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
+	BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1),
+	BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
+	BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
+	BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
+/*	BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
+	BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_INTERN
+	| BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __initdata =
+BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_INTERN, 0, 0);
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);


 #ifdef PMAC_SUPPORT_AUTOMUTE
@@ -347,19 +579,30 @@ static int snd_pmac_burgundy_detect_head
 	return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0;
 }

-static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip,
int do_notify)
+static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip,
+					      int do_notify)
 {
 	if (chip->auto_mute) {
+		int imac = machine_is_compatible("iMac");
 		int reg, oreg;
-		reg = oreg = snd_pmac_burgundy_rcb(chip,
MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
-		reg &= ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT |
BURGUNDY_OUTPUT_INTERN);
+		reg = oreg = snd_pmac_burgundy_rcb(chip,
+				MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+		reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
+				| BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
+			: ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
+				| BURGUNDY_OUTPUT_INTERN);
 		if (snd_pmac_burgundy_detect_headphone(chip))
-			reg |= BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT;
+			reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
+				: (BURGUNDY_OUTPUT_LEFT
+					| BURGUNDY_OUTPUT_RIGHT);
 		else
-			reg |= BURGUNDY_OUTPUT_INTERN;
+			reg |= imac ? (BURGUNDY_OUTPUT_LEFT
+					| BURGUNDY_OUTPUT_RIGHT)
+				: (BURGUNDY_OUTPUT_INTERN);
 		if (do_notify && reg == oreg)
 			return;
-		snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
+		snd_pmac_burgundy_wcb(chip,
+				MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
 		if (do_notify) {
 			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 				       &chip->master_sw_ctl->id);
@@ -378,6 +621,7 @@ static void snd_pmac_burgundy_update_aut
  */
 int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
 {
+	int imac = machine_is_compatible("iMac");
 	int i, err;

 	/* Checks to see the chip is alive and kicking */
@@ -386,7 +630,7 @@ int __init snd_pmac_burgundy_init(struct
 		return 1;
 	}

-	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
+	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
 			   DEF_BURGUNDY_OUTPUTENABLES);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
 			   DEF_BURGUNDY_MORE_OUTPUTENABLES);
@@ -396,7 +640,8 @@ int __init snd_pmac_burgundy_init(struct
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21,
 			   DEF_BURGUNDY_INPSEL21);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3,
-			   DEF_BURGUNDY_INPSEL3);
+			   imac ? DEF_BURGUNDY_INPSEL3_IMAC
+			   : DEF_BURGUNDY_INPSEL3_PMAC);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD,
 			   DEF_BURGUNDY_GAINCD);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE,
@@ -422,23 +667,51 @@ int __init snd_pmac_burgundy_init(struct
 	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC,
 			   DEF_BURGUNDY_VOLMIC);

-	if (chip->hp_stat_mask == 0)
+	if (chip->hp_stat_mask == 0) {
 		/* set headphone-jack detection bit */
-		chip->hp_stat_mask = 0x04;
-
+		if (imac)
+			chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER
+				| BURGUNDY_HPDETECT_IMAC_LOWER
+				| BURGUNDY_HPDETECT_IMAC_SIDE;
+		else
+			chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK;
+	}
 	/*
 	 * build burgundy mixers
 	 */
 	strcpy(chip->card->mixername, "PowerMac Burgundy");

 	for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
-		if ((err = snd_ctl_add(chip->card,
snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
+		if ((err = snd_ctl_add(chip->card,
+		    snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
+			return err;
+	}
+	for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac)
+			: ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) {
+		if ((err = snd_ctl_add(chip->card,
+		    snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i]
+		    : &snd_pmac_burgundy_mixers_pmac[i], chip))) < 0)
 			return err;
 	}
-	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_master_sw, chip);
+	chip->master_sw_ctl = snd_ctl_new1(imac
+			? &snd_pmac_burgundy_master_sw_imac
+			: &snd_pmac_burgundy_master_sw_pmac, chip);
 	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 		return err;
-	chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_speaker_sw, chip);
+	chip->master_sw_ctl = snd_ctl_new1(imac
+			? &snd_pmac_burgundy_line_sw_imac
+			: &snd_pmac_burgundy_line_sw_pmac, chip);
+	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+		return err;
+	if (imac) {
+		chip->master_sw_ctl = snd_ctl_new1(
+				&snd_pmac_burgundy_hp_sw_imac, chip);
+		if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+			return err;
+	}
+	chip->speaker_sw_ctl = snd_ctl_new1(imac
+			? &snd_pmac_burgundy_speaker_sw_imac
+			: &snd_pmac_burgundy_speaker_sw_pmac, chip);
 	if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 		return err;
 #ifdef PMAC_SUPPORT_AUTOMUTE
--- sound/ppc/burgundy.h.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/burgundy.h	2008-04-05 22:02:44.000000000 +0300
@@ -22,6 +22,7 @@
 #ifndef __BURGUNDY_H
 #define __BURGUNDY_H

+#define MASK_ADDR_BURGUNDY_INPBOOST (0x10 << 12)
 #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12)
 #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12)

@@ -35,7 +36,10 @@
 #define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12)
 #define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12)

+#define MASK_ADDR_BURGUNDY_CAPTURESELECTS (0x2A << 12)
 #define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12)
+#define MASK_ADDR_BURGUNDY_VOLMIX01 (0x2D << 12)
+#define MASK_ADDR_BURGUNDY_VOLMIX23 (0x2E << 12)
 #define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12)

 #define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12)
@@ -45,6 +49,10 @@
 #define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12)
 #define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12)
 #define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12)
+#define MASK_ADDR_BURGUNDY_ATTENMONO (0x65 << 12)
+
+#define MASK_ADDR_BURGUNDY_HOSTIFAD (0x78 << 12)
+#define MASK_ADDR_BURGUNDY_HOSTIFEH (0x79 << 12)

 #define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1)
 #define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2)
@@ -59,21 +67,22 @@

 /* These are all default values for the burgundy */
 #define DEF_BURGUNDY_INPSEL21 (0xAA)
-#define DEF_BURGUNDY_INPSEL3 (0x0A)
+#define DEF_BURGUNDY_INPSEL3_IMAC (0x0A)
+#define DEF_BURGUNDY_INPSEL3_PMAC (0x05)

 #define DEF_BURGUNDY_GAINCD (0x33)
 #define DEF_BURGUNDY_GAINLINE (0x44)
 #define DEF_BURGUNDY_GAINMIC (0x44)
 #define DEF_BURGUNDY_GAINMODEM (0x06)

-/* Remember: lowest volume here is 0x9b */
+/* Remember: lowest volume here is 0x9B (155) */
 #define DEF_BURGUNDY_VOLCD (0xCCCCCCCC)
 #define DEF_BURGUNDY_VOLLINE (0x00000000)
 #define DEF_BURGUNDY_VOLMIC (0x00000000)
 #define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC)

-#define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f)
-#define DEF_BURGUNDY_OUTPUTENABLES (0x0A)
+#define DEF_BURGUNDY_OUTPUTSELECTS (0x010F010F)
+#define DEF_BURGUNDY_OUTPUTENABLES (0x0100000A)

 /* #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) */ /* too loud */
 #define DEF_BURGUNDY_MASTER_VOLUME (0xDDDDDDDD)
@@ -84,12 +93,22 @@
 #define DEF_BURGUNDY_ATTENLINEOUT (0xCC)
 #define DEF_BURGUNDY_ATTENHP (0xCC)

-/* OUTPUTENABLES bits */
+/* MORE_OUTPUTENABLES bits */
 #define BURGUNDY_OUTPUT_LEFT	0x02
 #define BURGUNDY_OUTPUT_RIGHT	0x04
+#define BURGUNDY_LINEOUT_LEFT	0x08
+#define BURGUNDY_LINEOUT_RIGHT	0x10
+#define BURGUNDY_HP_LEFT	0x20
+#define BURGUNDY_HP_RIGHT	0x40
 #define BURGUNDY_OUTPUT_INTERN	0x80

-/* volume offset */
+/* Headphone detection bits */
+#define BURGUNDY_HPDETECT_PMAC_BACK	0x04
+#define BURGUNDY_HPDETECT_IMAC_SIDE	0x04
+#define BURGUNDY_HPDETECT_IMAC_UPPER	0x08
+#define BURGUNDY_HPDETECT_IMAC_LOWER	0x01
+
+/* Volume offset */
 #define BURGUNDY_VOLUME_OFFSET	155

 #endif /* __BURGUNDY_H */

^ permalink raw reply

* [PATCH 002/003] snd-powermac: AWACS and Screamer mixers for PM7500, Beige, and iMac SL
From: Risto Suominen @ 2008-04-07 13:28 UTC (permalink / raw)
  To: perex; +Cc: LinuxPPC-dev

From: Risto Suominen <Risto.Suominen@gmail.com>

Add mixer controls and correct headphone detection bits for PowerMacs
7300/7500 (AWACS) and G3 Beige (Screamer), and iMac G3 Slot-loading
(Screamer).

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
---
Kernel version 2.6.25-rc8 (probably any 2.6)

--- sound/ppc/awacs.c.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/awacs.c	2008-04-07 11:24:08.108621048 +0300
@@ -141,7 +141,7 @@ static int snd_pmac_awacs_info_volume(st
 	uinfo->value.integer.max = 15;
 	return 0;
 }
-
+
 static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,
 				     struct snd_ctl_elem_value *ucontrol)
 {
@@ -267,7 +267,8 @@ static int snd_pmac_awacs_put_switch(str
 static void awacs_set_cuda(int reg, int val)
 {
 	struct adb_request req;
-	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, reg, val);
+	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a,
+			reg, val);
 	while (! req.complete)
 		cuda_poll();
 }
@@ -289,11 +290,11 @@ static void awacs_amp_set_tone(struct aw
 /*
  * vol = 0 - 31 (attenuation), 32 = mute bit, stereo
  */
-static int awacs_amp_set_vol(struct awacs_amp *amp, int index, int
lvol, int rvol,
-			     int do_check)
+static int awacs_amp_set_vol(struct awacs_amp *amp, int index,
+			     int lvol, int rvol, int do_check)
 {
 	if (do_check && amp->amp_vol[index][0] == lvol &&
-	    amp->amp_vol[index][1] == rvol)
+			amp->amp_vol[index][1] == rvol)
 		return 0;
 	awacs_set_cuda(3 + index, lvol);
 	awacs_set_cuda(5 + index, rvol);
@@ -337,7 +338,7 @@ static int snd_pmac_awacs_info_volume_am
 	uinfo->value.integer.max = 31;
 	return 0;
 }
-
+
 static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
@@ -361,8 +362,10 @@ static int snd_pmac_awacs_put_volume_amp
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);

-	vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) |
(amp->amp_vol[index][0] & 32);
-	vol[1] = (31 - (ucontrol->value.integer.value[1] & 31)) |
(amp->amp_vol[index][1] & 32);
+	vol[0] = (31 - (ucontrol->value.integer.value[0] & 31))
+		| (amp->amp_vol[index][0] & 32);
+	vol[1] = (31 - (ucontrol->value.integer.value[1] & 31))
+		| (amp->amp_vol[index][1] & 32);
 	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
 }

@@ -374,8 +377,10 @@ static int snd_pmac_awacs_get_switch_amp
 	struct awacs_amp *amp = chip->mixer_data;
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);
-	ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) ? 0 : 1;
-	ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) ? 0 : 1;
+	ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32)
+					? 0 : 1;
+	ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32)
+					? 0 : 1;
 	return 0;
 }

@@ -389,8 +394,10 @@ static int snd_pmac_awacs_put_switch_amp
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);

-	vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) |
(amp->amp_vol[index][0] & 31);
-	vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32) |
(amp->amp_vol[index][1] & 31);
+	vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32)
+		| (amp->amp_vol[index][0] & 31);
+	vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32)
+		| (amp->amp_vol[index][1] & 31);
 	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
 }

@@ -403,7 +410,7 @@ static int snd_pmac_awacs_info_tone_amp(
 	uinfo->value.integer.max = 14;
 	return 0;
 }
-
+
 static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_value *ucontrol)
 {
@@ -445,7 +452,7 @@ static int snd_pmac_awacs_info_master_am
 	uinfo->value.integer.max = 99;
 	return 0;
 }
-
+
 static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
@@ -493,14 +500,14 @@ static struct snd_kcontrol_new snd_pmac_
 	  .private_value = AMP_CH_HD,
 	},
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "Tone Control - Bass",
+	  .name = "Tone Control - Bass Playback Volume",
 	  .info = snd_pmac_awacs_info_tone_amp,
 	  .get = snd_pmac_awacs_get_tone_amp,
 	  .put = snd_pmac_awacs_put_tone_amp,
 	  .private_value = 0,
 	},
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "Tone Control - Treble",
+	  .name = "Tone Control - Treble Playback Volume",
 	  .info = snd_pmac_awacs_info_tone_amp,
 	  .get = snd_pmac_awacs_get_tone_amp,
 	  .put = snd_pmac_awacs_put_tone_amp,
@@ -544,7 +551,7 @@ static int snd_pmac_screamer_mic_boost_i
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 1;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 2;
+	uinfo->value.integer.max = 3;
 	return 0;
 }

@@ -552,16 +559,14 @@ static int snd_pmac_screamer_mic_boost_g
 					   struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int val;
+	int val = 0;
 	unsigned long flags;

 	spin_lock_irqsave(&chip->reg_lock, flags);
 	if (chip->awacs_reg[6] & MASK_MIC_BOOST)
-		val = 2;
-	else if (chip->awacs_reg[0] & MASK_GAINLINE)
-		val = 1;
-	else
-		val = 0;
+		val |= 2;
+	if (chip->awacs_reg[0] & MASK_GAINLINE)
+		val |= 1;
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	ucontrol->value.integer.value[0] = val;
 	return 0;
@@ -578,11 +583,10 @@ static int snd_pmac_screamer_mic_boost_p
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	val0 = chip->awacs_reg[0] & ~MASK_GAINLINE;
 	val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST;
-	if (ucontrol->value.integer.value[0] > 0) {
+	if (ucontrol->value.integer.value[0] & 1)
 		val0 |= MASK_GAINLINE;
-		if (ucontrol->value.integer.value[0] > 1)
-			val6 |= MASK_MIC_BOOST;
-	}
+	if (ucontrol->value.integer.value[0] & 2)
+		val6 |= MASK_MIC_BOOST;
 	if (val0 != chip->awacs_reg[0]) {
 		snd_pmac_awacs_write_reg(chip, 0, val0);
 		changed = 1;
@@ -599,9 +603,32 @@ static int snd_pmac_screamer_mic_boost_p
  * lists of mixer elements
  */
 static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = {
-	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
 	AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
-	AWACS_VOLUME("Capture Volume", 0, 4, 0),
+	AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
+/*	AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __initdata = {
+	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+	AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
+	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+	AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = {
+	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = {
+	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };

@@ -621,35 +648,61 @@ static struct snd_kcontrol_new snd_pmac_
 static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);

+static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata =
+AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
+
 static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
-	AWACS_SWITCH("Mic Boost", 0, SHIFT_GAINLINE, 0),
+	AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };

 static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = {
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "Mic Boost",
+	  .name = "Mic Boost Capture Volume",
 	  .info = snd_pmac_screamer_mic_boost_info,
 	  .get = snd_pmac_screamer_mic_boost_get,
 	  .put = snd_pmac_screamer_mic_boost_put,
 	},
 };

+static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __initdata =
+{
+	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __initdata =
+{
+	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+	AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __initdata =
+{
+	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+	AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+};
+
 static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {
 	AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1),
 };
+
 static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
 AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);

+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata =
+AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
+

 /*
  * add new mixer elements to the card
  */
-static int build_mixers(struct snd_pmac *chip, int nums, struct
snd_kcontrol_new *mixers)
+static int build_mixers(struct snd_pmac *chip, int nums,
+			struct snd_kcontrol_new *mixers)
 {
 	int i, err;

 	for (i = 0; i < nums; i++) {
-		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip))) < 0)
+		if ((err = snd_ctl_add(chip->card,
+				       snd_ctl_new1(&mixers[i], chip))) < 0)
 			return err;
 	}
 	return 0;
@@ -699,8 +752,10 @@ static void snd_pmac_awacs_resume(struct
 #ifdef PMAC_AMP_AVAIL
 	if (chip->mixer_data) {
 		struct awacs_amp *amp = chip->mixer_data;
-		awacs_amp_set_vol(amp, 0, amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
-		awacs_amp_set_vol(amp, 1, amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
+		awacs_amp_set_vol(amp, 0,
+				  amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
+		awacs_amp_set_vol(amp, 1,
+				  amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
 		awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
 		awacs_amp_set_master(amp, amp->amp_master);
 	}
@@ -708,6 +763,14 @@ static void snd_pmac_awacs_resume(struct
 }
 #endif /* CONFIG_PM */

+#define IS_PM7500 (machine_is_compatible("AAPL,7500"))
+#define IS_BEIGE (machine_is_compatible("AAPL,Gossamer"))
+#define IS_IMAC (machine_is_compatible("PowerMac2,1") \
+		|| machine_is_compatible("PowerMac2,2") \
+		|| machine_is_compatible("PowerMac4,1"))
+
+static int imac;
+
 #ifdef PMAC_SUPPORT_AUTOMUTE
 /*
  * auto-mute stuffs
@@ -750,9 +813,16 @@ static void snd_pmac_awacs_update_automu
 		} else
 #endif
 		{
-			int reg = chip->awacs_reg[1] | (MASK_HDMUTE|MASK_SPKMUTE);
+			int reg = chip->awacs_reg[1]
+				| (MASK_HDMUTE | MASK_SPKMUTE);
+			if (imac) {
+				reg &= ~MASK_SPKMUTE;
+				reg &= ~MASK_PAROUT1;
+			}
 			if (snd_pmac_awacs_detect_headphone(chip))
 				reg &= ~MASK_HDMUTE;
+			else if (imac)
+				reg |= MASK_PAROUT1;
 			else
 				reg &= ~MASK_SPKMUTE;
 			if (do_notify && reg == chip->awacs_reg[1])
@@ -778,8 +848,11 @@ static void snd_pmac_awacs_update_automu
 int __init
 snd_pmac_awacs_init(struct snd_pmac *chip)
 {
+	int pm7500 = IS_PM7500;
+	int beige = IS_BEIGE;
 	int err, vol;

+	imac = IS_IMAC;
 	/* looks like MASK_GAINLINE triggers something, so we set here
 	 * as start-up
 	 */
@@ -787,7 +860,7 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 	chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE;
 	/* FIXME: Only machines with external SRS module need MASK_PAROUT */
 	if (chip->has_iic || chip->device_id == 0x5 ||
-	    /*chip->_device_id == 0x8 || */
+	    /* chip->_device_id == 0x8 || */
 	    chip->device_id == 0xb)
 		chip->awacs_reg[1] |= MASK_PAROUT;
 	/* get default volume from nvram */
@@ -798,8 +871,10 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 	chip->awacs_reg[2] = vol;
 	chip->awacs_reg[4] = vol;
 	if (chip->model == PMAC_SCREAMER) {
-		chip->awacs_reg[5] = vol; /* FIXME: screamer has loopthru vol control */
-		chip->awacs_reg[6] = MASK_MIC_BOOST; /* FIXME: maybe should be vol
<< 3 for PCMCIA speaker */
+		/* FIXME: screamer has loopthru vol control */
+		chip->awacs_reg[5] = vol;
+		/* FIXME: maybe should be vol << 3 for PCMCIA speaker */
+		chip->awacs_reg[6] = MASK_MIC_BOOST;
 		chip->awacs_reg[7] = 0;
 	}

@@ -815,7 +890,8 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 			return -ENOMEM;
 		chip->mixer_data = amp;
 		chip->mixer_free = awacs_amp_free;
-		awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */
+		/* mute and zero vol */
+		awacs_amp_set_vol(amp, 0, 63, 63, 0);
 		awacs_amp_set_vol(amp, 1, 63, 63, 0);
 		awacs_amp_set_tone(amp, 7, 7); /* 0 dB */
 		awacs_amp_set_master(amp, 79); /* 0 dB */
@@ -826,20 +902,25 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 		/* set headphone-jack detection bit */
 		switch (chip->model) {
 		case PMAC_AWACS:
-			chip->hp_stat_mask = 0x04;
+			chip->hp_stat_mask = pm7500 ? MASK_HDPCONN
+				: MASK_LOCONN;
 			break;
 		case PMAC_SCREAMER:
 			switch (chip->device_id) {
 			case 0x08:
-				/* 1 = side jack, 2 = front jack */
-				chip->hp_stat_mask = 0x03;
+			case 0x0B:
+				chip->hp_stat_mask = imac
+					? MASK_LOCONN_IMAC |
+					MASK_HDPLCONN_IMAC |
+					MASK_HDPRCONN_IMAC
+					: MASK_HDPCONN;
 				break;
 			case 0x00:
 			case 0x05:
-				chip->hp_stat_mask = 0x04;
+				chip->hp_stat_mask = MASK_LOCONN;
 				break;
 			default:
-				chip->hp_stat_mask = 0x08;
+				chip->hp_stat_mask = MASK_HDPCONN;
 				break;
 			}
 			break;
@@ -857,15 +938,37 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 	if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
 				snd_pmac_awacs_mixers)) < 0)
 		return err;
-	if (chip->model == PMAC_SCREAMER)
+	if (beige)
+		;
+	else if (chip->model == PMAC_SCREAMER)
 		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
 				   snd_pmac_screamer_mixers2);
-	else
+	else if (!pm7500)
 		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
 				   snd_pmac_awacs_mixers2);
 	if (err < 0)
 		return err;
-	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
+	if (pm7500)
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
+				   snd_pmac_awacs_mixers_pmac7500);
+	else if (beige)
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_screamer_mixers_beige),
+				   snd_pmac_screamer_mixers_beige);
+	else if (imac)
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
+				   snd_pmac_screamer_mixers_imac);
+	else
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),
+				   snd_pmac_awacs_mixers_pmac);
+	if (err < 0)
+		return err;
+	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac)
+			? &snd_pmac_awacs_master_sw_imac
+			: &snd_pmac_awacs_master_sw, chip);
 	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 		return err;
 #ifdef PMAC_AMP_AVAIL
@@ -876,35 +979,58 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 		 * screamer registers.
 		 * in this case, it seems the route C is not used.
 		 */
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
+		if ((err = build_mixers(chip,
+					ARRAY_SIZE(snd_pmac_awacs_amp_vol),
 					snd_pmac_awacs_amp_vol)) < 0)
 			return err;
 		/* overwrite */
-		chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw, chip);
+		chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw,
+						   chip);
 		if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 			return err;
-		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw, chip);
+		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw,
+						    chip);
 		if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 			return err;
 	} else
 #endif /* PMAC_AMP_AVAIL */
 	{
 		/* route A = headphone, route C = speaker */
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
+		if ((err = build_mixers(chip,
+					ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
 					snd_pmac_awacs_speaker_vol)) < 0)
 			return err;
-		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
+		chip->speaker_sw_ctl = snd_ctl_new1(imac
+				? &snd_pmac_awacs_speaker_sw_imac
+				: &snd_pmac_awacs_speaker_sw, chip);
 		if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 			return err;
 	}

-	if (chip->model == PMAC_SCREAMER) {
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
-					snd_pmac_screamer_mic_boost)) < 0)
+	if (beige) {
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),
+				snd_pmac_screamer_mic_boost_beige)) < 0)
+			return err;
+	} else if (imac) {
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac),
+				snd_pmac_screamer_mic_boost_imac)) < 0)
+			return err;
+	} else if (chip->model == PMAC_SCREAMER) {
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_screamer_mic_boost),
+				snd_pmac_screamer_mic_boost)) < 0)
+			return err;
+	} else if (pm7500) {
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500),
+				snd_pmac_awacs_mic_boost_pmac7500)) < 0)
 			return err;
 	} else {
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
-					snd_pmac_awacs_mic_boost)) < 0)
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_awacs_mic_boost),
+				snd_pmac_awacs_mic_boost)) < 0)
 			return err;
 	}

--- sound/ppc/awacs.h.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/awacs.h	2008-04-07 11:26:58.198763416 +0300
@@ -116,6 +116,11 @@ struct awacs_regs {
 #define MASK_HDMUTE	MASK_AMUTE
 #define SHIFT_HDMUTE	9
 #define MASK_PAROUT	(0x3 << 10)	/* Parallel Out (???) */
+#define MASK_PAROUT0	(0x1 << 10)	/* Parallel Out (???) */
+#define MASK_PAROUT1	(0x1 << 11)	/* Parallel Out (enable speaker) */
+#define SHIFT_PAROUT	10
+#define SHIFT_PAROUT0	10
+#define SHIFT_PAROUT1	11

 #define SAMPLERATE_48000	(0x0 << 3)	/* 48 or 44.1 kHz */
 #define SAMPLERATE_32000	(0x1 << 3)	/* 32 or 29.4 kHz */
@@ -152,8 +157,15 @@ struct awacs_regs {
 #define MASK_REVISION	(0xf << 12)	/* Revision Number */
 #define MASK_MFGID	(0xf << 8)	/* Mfg. ID */
 #define MASK_CODSTATRES	(0xf << 4)	/* bits 4 - 7 reserved */
-#define MASK_INPPORT	(0xf)		/* Input Port */
-#define MASK_HDPCONN	8		/* headphone plugged in */
+#define MASK_INSENSE	(0xf)		/* port sense bits: */
+#define MASK_HDPCONN		8	/* headphone plugged in */
+#define MASK_LOCONN		4	/* line-out plugged in */
+#define MASK_LICONN		2	/* line-in plugged in */
+#define MASK_MICCONN		1	/* microphone plugged in */
+#define MASK_LICONN_IMAC	8	/* line-in plugged in */
+#define MASK_HDPRCONN_IMAC	4	/* headphone right plugged in */
+#define MASK_HDPLCONN_IMAC	2	/* headphone left plugged in */
+#define MASK_LOCONN_IMAC	1	/* line-out plugged in */

 /* Clipping Count Reg Bit Masks */
 /* -------- ----- --- --- ----- */
@@ -163,7 +175,8 @@ struct awacs_regs {
 /* DBDMA ChannelStatus Bit Masks */
 /* ----- ------------- --- ----- */
 #define MASK_CSERR	(0x1 << 7)	/* Error */
-#define MASK_EOI	(0x1 << 6)	/* End of Input -- only for Input Channel */
+#define MASK_EOI	(0x1 << 6)	/* End of Input --
+					   only for Input Channel */
 #define MASK_CSUNUSED	(0x1f << 1)	/* bits 1-5 not used */
 #define MASK_WAIT	(0x1)		/* Wait */

^ permalink raw reply

* [PATCH 001/003] snd-powermac: enable headphone detection
From: Risto Suominen @ 2008-04-07 13:28 UTC (permalink / raw)
  To: perex; +Cc: LinuxPPC-dev

From: Risto Suominen <Risto.Suominen@gmail.com>

Enable port change interrupt while initialising AWACS, Screamer, and
Burgundy chipsets.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
---
Kernel version 2.6.25-rc8 (probably any 2.6)

--- sound/ppc/pmac.c.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/pmac.c	2008-04-07 12:18:47.503077312 +0300
@@ -214,7 +214,7 @@ static int snd_pmac_pcm_prepare(struct s
 	int rate_index;
 	long offset;
 	struct pmac_stream *astr;
-	
+
 	rec->dma_size = snd_pcm_lib_buffer_bytes(subs);
 	rec->period_size = snd_pcm_lib_period_bytes(subs);
 	rec->nperiods = rec->dma_size / rec->period_size;
@@ -643,7 +643,7 @@ static int snd_pmac_pcm_close(struct snd
 	/* reset constraints */
 	astr->cur_freqs = chip->freqs_ok;
 	astr->cur_formats = chip->formats_ok;
-	
+
 	return 0;
 }

@@ -1063,6 +1063,10 @@ static int __init snd_pmac_detect(struct
 	else {
 		struct pci_dev *pdev = NULL;

+#ifndef for_each_pci_dev
+#define for_each_pci_dev(d) \
+		while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
+#endif
 		for_each_pci_dev(pdev) {
 			struct device_node *np = pci_device_to_OF_node(pdev);
 			if (np && np == macio->of_node) {
@@ -1300,9 +1304,9 @@ int __init snd_pmac_new(struct snd_card

 	snd_pmac_sound_feature(chip, 1);

-	/* reset */
-	if (chip->model == PMAC_AWACS)
-		out_le32(&chip->awacs->control, 0x11);
+	/* reset & enable interrupts */
+	if (chip->model <= PMAC_BURGUNDY)
+		out_le32(&chip->awacs->control, chip->control_mask);

 	/* Powerbooks have odd ways of enabling inputs such as
 	   an expansion-bay CD or sound from an internal modem

^ permalink raw reply

* Re: Kilauea: kernel hangs when using ARCH=powerpc
From: Josh Boyer @ 2008-04-07 13:23 UTC (permalink / raw)
  To: bernhard.weirich; +Cc: linuxppc-dev
In-Reply-To: <1207562631.6678.10.camel@hactar>

On Mon, 2008-04-07 at 12:03 +0200, Bernhard Weirich wrote:
> Hello!
> 
> When I build the kernel for my kilauea board using ARCH=ppc everything
> works fine.
> Since ppc is deprecated I'd like to switch to powerpc, but if I do so
> the kernel does not produce any output.
> There is just the last line of the prompt from the bootloader.
> In both cases I built with kilauea_defconfig
> 
> I tried the Denx ELDK (4.2) compiler 4.2.2, the toolchain generated by
> Buildroot and different kernel versions from the denx repository.
> The Kilauea board is Version 1.11b.
> 
> Any ideas what is going wrong?

You need to be sure to load the device tree blob in U-Boot, and ensure
that your bootargs environment variable contains the proper values for
console.

josh

^ permalink raw reply

* Re: [PATCH v2] powerpc: Add irqtrace support for 32-bit powerpc
From: Johannes Berg @ 2008-04-07 13:10 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev
In-Reply-To: <1207543791.10388.468.camel@pasglop>

[-- Attachment #1: Type: text/plain, Size: 456 bytes --]


> Note that I've been wondering wether we should attempt to trace all
> those IRQ state change internally to the exception code. I've looked at
> not doing it, which simplifies things a bit.
> 
> Unfortunately, that will make us occasionally trace redundant
> enable/disable (which isn't a big problem per-se, just counters).

We already have a huge number of redundant enable/disable, about 40% of
all events on both 32 and 64-bit.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* Re: [RFC][PATCH] initial port of fixmap over from x86 for ppc32
From: Kumar Gala @ 2008-04-07 13:09 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, hollisb
In-Reply-To: <18425.24938.332852.315571@cargo.ozlabs.ibm.com>


On Apr 6, 2008, at 6:48 PM, Paul Mackerras wrote:
> Kumar Gala writes:
>
>> Wanted to get any feedback on this initial port of the fixmap  
>> support over
>> from x86.  There are a few TODOs:
>
> I have no objection in principle, but your patch below imports a few
> things that aren't (and won't be) needed on powerpc AFAICS -- for
> example, we don't need FIX_VDSO, since our VDSO is mapped into user
> space at the 1MB point (by default).

Agreed.

> You have FIX_PCIE_MCFG in there too (keyed off CONFIG_PCI_MMCONFIG
> which we don't have and don't want to have).  If you need to map in
> PCIe config space, what's wrong with just using ioremap?  Why do you
> need to have a fixed virtual address for it?

Ben has commented on this.  I know on the 83xx systems we have two  
PCIe PHBs that would require ioremapping 512M of virtual address space  
which we don't have if the system has any large amount of memory.

> More generally, I think we need to take an overall look at what things
> we are using fixed virtual addresses for, and why they need to be
> fixed.  If there are indeed several such things then we can introduce
> the fixmap stuff.

The list as I see it:
* kmap
* pci-e config for 4xx/83xx
* kexec/kdump (ben commented on this when Dale posted his patches for  
ppc32 support)

future:
* possible usage by HV

since we already have three users and a possible fourth it seems like  
a useful change.

- k

^ permalink raw reply

* Re: [PATCH 3/4] PowerPC: Add PCI entry to 440EPx Sequoia DTS.
From: Valentine Barshak @ 2008-04-07 13:01 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linuxppc-dev
In-Reply-To: <47F7A935.3080803@ru.mvista.com>

Sergei Shtylyov wrote:
> Valentine Barshak wrote:
> 
>> This adds PCI entry to PowerPC 440EPx Sequoia DTS.
> 
>> Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
> 
>> --- linux-2.6.orig/arch/powerpc/boot/dts/sequoia.dts    2007-12-21 
>> 17:14:17.000000000 +0300
>> +++ linux-2.6/arch/powerpc/boot/dts/sequoia.dts    2007-12-21 
>> 17:18:32.000000000 +0300
>> @@ -324,6 +324,33 @@
>>                  has-new-stacr-staopc;
>>              };
>>          };
>> +
>> +        PCI0: pci@1ec000000 {
>> +            device_type = "pci";
>> +            #interrupt-cells = <1>;
>> +            #size-cells = <2>;
>> +            #address-cells = <3>;
>> +            compatible = "ibm,plb440epx-pci", "ibm,plb-pci";
>> +            primary;
>> +            reg = <1 eec00000 8    /* Config space access */
>> +                   1 eed00000 4    /* IACK */
>> +                   1 eed00000 4    /* Special cycle */
>> +                   1 ef400000 40>;    /* Internal registers */
>> +
>> +            /* Outbound ranges, one memory and one IO,
>> +             * later cannot be changed. Chip supports a second
>> +             * IO range but we don't use it for now
>> +             */
>> +            ranges = <02000000 0 80000000 1 80000000 0 10000000
> 
>    I wonder why the AMCC's Sequoia/Rainier manual has PCI memory mapped 
> at 0x80000000-0xbfffffff? The 0x80000000-0x8fffffff mapping was assumed 
> by arch/ppc/ code.  What/why changed here?

The addresses in the manual are relative to bus base. PCI controller is 
located on the PLB and PLB base address is 0x100000000ULL on Sequoia.
Older PPC code has ioremap64 function that did the 64 to 32-bit trick
It's been abolished. The kernel has support for 64-bit physical 
addresses on 32-bit. IMHO there's no big reason to keep doing that 
address trick. However, there are some drivers that use unsigned long 
for storing physical addresses. This is wrong, since 
pci_resource_start() returns a resource_size_t value. I think it's these 
drivers that have to be fixed instead of adding workarounds to ppc4xx code.
Thanks,
Valentine.

>    As we now both know, having PCI memory space mapped beyound 4 GB 
> makes some drivers misbehave as they use 'unsigned long' to store the 
> result of pci_resource_start() and later ioremap() this truncated value 
> -- which is 64-bit on Sequoia due to CONFIG_RESOURCE_64BIT=y that is 
> needed to store the beyond-4GB addresses.
> 
>> +                01000000 0 00000000 1 e8000000 0 00100000>;
>> +
>> +            /* Inbound 2GB range starting at 0 */
>> +            dma-ranges = <42000000 0 0 0 0 0 80000000>;
>> +
>> +            /* All PCI interrupts are routed to IRQ 67 */
>> +            interrupt-map-mask = <0000 0 0 0>;
>> +            interrupt-map = < 0000 0 0 0 &UIC2 3 8 >;
>> +        };
>>      };
> 
> WBR, Sergei

^ permalink raw reply

* Re: [PATCH] [POWERPC] Update linker script to properly set physical addresses
From: Kumar Gala @ 2008-04-07 13:00 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18425.47270.756180.55444@cargo.ozlabs.ibm.com>


On Apr 7, 2008, at 1:01 AM, Paul Mackerras wrote:
> Kumar Gala writes:
>
>> We can set LOAD_OFFSET and use the AT attribute on sections and the
>> linker will properly set the physical address of the LOAD program
>> header for us.
>
> Nice...
>
>> #define KERNELBASE      ASM_CONST(CONFIG_KERNEL_START)
>> #define PAGE_OFFSET	ASM_CONST(CONFIG_PAGE_OFFSET)
>> +#define LOAD_OFFSET	ASM_CONST((CONFIG_KERNEL_START- 
>> CONFIG_PHYSICAL_START))
>
> I think this should be CONFIG_PAGE_OFFSET - CONFIG_PHYSICAL_START
> though.

Disagree (assuming I'm thinking straight first thing in the morning).

PAGE_OFFSET is virt address of the beginning of memory, where  
KERNEL_START is virt address of start of kernel text.
PHYSICAL_START is physical address of KERNEL_START.

(I tried to match x86's definitions here as per Milton's request to be  
consistent).

- k

^ permalink raw reply

* [PATCH] IB/ehca: extend query_device() and query_port() to support all values for ibv_devinfo
From: Stefan Roscher @ 2008-04-07 12:57 UTC (permalink / raw)
  To: ewg, general, linux-kernel, linuxppc-dev, rolandd; +Cc: fenkes, raisch

Also, introduce a few inline helper functions to make the code more readable.

Signed-off-by: Stefan Roscher <stefan.roscher@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_hca.c |  128 ++++++++++++++++++++------------
 1 files changed, 80 insertions(+), 48 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index 8832123..f89c5f8 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -43,6 +43,11 @@
 #include "ehca_iverbs.h"
 #include "hcp_if.h"
 
+static inline unsigned int limit_uint(unsigned int value)
+{
+	return min_t(unsigned int, value, INT_MAX);
+}
+
 int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
 {
 	int i, ret = 0;
@@ -83,37 +88,40 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
 	props->vendor_id       = rblock->vendor_id >> 8;
 	props->vendor_part_id  = rblock->vendor_part_id >> 16;
 	props->hw_ver          = rblock->hw_ver;
-	props->max_qp          = min_t(unsigned, rblock->max_qp, INT_MAX);
-	props->max_qp_wr       = min_t(unsigned, rblock->max_wqes_wq, INT_MAX);
-	props->max_sge         = min_t(unsigned, rblock->max_sge, INT_MAX);
-	props->max_sge_rd      = min_t(unsigned, rblock->max_sge_rd, INT_MAX);
-	props->max_cq          = min_t(unsigned, rblock->max_cq, INT_MAX);
-	props->max_cqe         = min_t(unsigned, rblock->max_cqe, INT_MAX);
-	props->max_mr          = min_t(unsigned, rblock->max_mr, INT_MAX);
-	props->max_mw          = min_t(unsigned, rblock->max_mw, INT_MAX);
-	props->max_pd          = min_t(unsigned, rblock->max_pd, INT_MAX);
-	props->max_ah          = min_t(unsigned, rblock->max_ah, INT_MAX);
-	props->max_fmr         = min_t(unsigned, rblock->max_mr, INT_MAX);
+	props->max_qp          = limit_uint(rblock->max_qp);
+	props->max_qp_wr       = limit_uint(rblock->max_wqes_wq);
+	props->max_sge         = limit_uint(rblock->max_sge);
+	props->max_sge_rd      = limit_uint(rblock->max_sge_rd);
+	props->max_cq          = limit_uint(rblock->max_cq);
+	props->max_cqe         = limit_uint(rblock->max_cqe);
+	props->max_mr          = limit_uint(rblock->max_mr);
+	props->max_mw          = limit_uint(rblock->max_mw);
+	props->max_pd          = limit_uint(rblock->max_pd);
+	props->max_ah          = limit_uint(rblock->max_ah);
+	props->max_ee          = limit_uint(rblock->max_rd_ee_context);
+	props->max_rdd         = limit_uint(rblock->max_rd_domain);
+	props->max_fmr         = limit_uint(rblock->max_mr);
+	props->local_ca_ack_delay  = limit_uint(rblock->local_ca_ack_delay);
+	props->max_qp_rd_atom  = limit_uint(rblock->max_rr_qp);
+	props->max_ee_rd_atom  = limit_uint(rblock->max_rr_ee_context);
+	props->max_res_rd_atom = limit_uint(rblock->max_rr_hca);
+	props->max_qp_init_rd_atom = limit_uint(rblock->max_act_wqs_qp);
+	props->max_ee_init_rd_atom = limit_uint(rblock->max_act_wqs_ee_context);
 
 	if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
-		props->max_srq         = props->max_qp;
-		props->max_srq_wr      = props->max_qp_wr;
+		props->max_srq         = limit_uint(props->max_qp);
+		props->max_srq_wr      = limit_uint(props->max_qp_wr);
 		props->max_srq_sge     = 3;
 	}
 
-	props->max_pkeys       = 16;
-	props->local_ca_ack_delay
-		= rblock->local_ca_ack_delay;
-	props->max_raw_ipv6_qp
-		= min_t(unsigned, rblock->max_raw_ipv6_qp, INT_MAX);
-	props->max_raw_ethy_qp
-		= min_t(unsigned, rblock->max_raw_ethy_qp, INT_MAX);
-	props->max_mcast_grp
-		= min_t(unsigned, rblock->max_mcast_grp, INT_MAX);
-	props->max_mcast_qp_attach
-		= min_t(unsigned, rblock->max_mcast_qp_attach, INT_MAX);
+	props->max_pkeys           = 16;
+	props->local_ca_ack_delay  = limit_uint(rblock->local_ca_ack_delay);
+	props->max_raw_ipv6_qp     = limit_uint(rblock->max_raw_ipv6_qp);
+	props->max_raw_ethy_qp     = limit_uint(rblock->max_raw_ethy_qp);
+	props->max_mcast_grp       = limit_uint(rblock->max_mcast_grp);
+	props->max_mcast_qp_attach = limit_uint(rblock->max_mcast_qp_attach);
 	props->max_total_mcast_qp_attach
-		= min_t(unsigned, rblock->max_total_mcast_qp_attach, INT_MAX);
+		= limit_uint(rblock->max_total_mcast_qp_attach);
 
 	/* translate device capabilities */
 	props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
@@ -128,6 +136,46 @@ query_device1:
 	return ret;
 }
 
+static inline int map_mtu(struct ehca_shca *shca, u32 fw_mtu)
+{
+	switch (fw_mtu) {
+	case 0x1:
+		return IB_MTU_256;
+	case 0x2:
+		return IB_MTU_512;
+	case 0x3:
+		return IB_MTU_1024;
+	case 0x4:
+		return IB_MTU_2048;
+	case 0x5:
+		return IB_MTU_4096;
+	default:
+		ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
+			 fw_mtu);
+		return 0;
+	}
+}
+
+static inline int map_number_of_vls(struct ehca_shca *shca, u32 vl_cap)
+{
+	switch (vl_cap) {
+	case 0x1:
+		return 1;
+	case 0x2:
+		return 2;
+	case 0x3:
+		return 4;
+	case 0x4:
+		return 8;
+	case 0x5:
+		return 15;
+	default:
+		ehca_err(&shca->ib_device, "invalid Vl Capability: %x.",
+			 vl_cap);
+		return 0;
+	}
+}
+
 int ehca_query_port(struct ib_device *ibdev,
 		    u8 port, struct ib_port_attr *props)
 {
@@ -152,31 +200,14 @@ int ehca_query_port(struct ib_device *ibdev,
 
 	memset(props, 0, sizeof(struct ib_port_attr));
 
-	switch (rblock->max_mtu) {
-	case 0x1:
-		props->active_mtu = props->max_mtu = IB_MTU_256;
-		break;
-	case 0x2:
-		props->active_mtu = props->max_mtu = IB_MTU_512;
-		break;
-	case 0x3:
-		props->active_mtu = props->max_mtu = IB_MTU_1024;
-		break;
-	case 0x4:
-		props->active_mtu = props->max_mtu = IB_MTU_2048;
-		break;
-	case 0x5:
-		props->active_mtu = props->max_mtu = IB_MTU_4096;
-		break;
-	default:
-		ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
-			 rblock->max_mtu);
-		break;
-	}
-
+	props->active_mtu = props->max_mtu = map_mtu(shca, rblock->max_mtu);
 	props->port_cap_flags  = rblock->capability_mask;
 	props->gid_tbl_len     = rblock->gid_tbl_len;
-	props->max_msg_sz      = rblock->max_msg_sz;
+	if (rblock->max_msg_sz) {
+		props->max_msg_sz      = rblock->max_msg_sz;
+	} else {
+		props->max_msg_sz      = 0x1 << 31;
+	}
 	props->bad_pkey_cntr   = rblock->bad_pkey_cntr;
 	props->qkey_viol_cntr  = rblock->qkey_viol_cntr;
 	props->pkey_tbl_len    = rblock->pkey_tbl_len;
@@ -186,6 +217,7 @@ int ehca_query_port(struct ib_device *ibdev,
 	props->sm_sl           = rblock->sm_sl;
 	props->subnet_timeout  = rblock->subnet_timeout;
 	props->init_type_reply = rblock->init_type_reply;
+	props->max_vl_num      = map_number_of_vls(shca, rblock->vl_cap);
 
 	if (rblock->state && rblock->phys_width) {
 		props->phys_state      = rblock->phys_pstate;
-- 
1.5.2

^ permalink raw reply related

* Re: Patches added to powerpc.git powerpc-next and master branches
From: Paul Mackerras @ 2008-04-07 12:25 UTC (permalink / raw)
  To: David Miller; +Cc: linuxppc-dev
In-Reply-To: <20080406.232220.69225114.davem@davemloft.net>

David Miller writes:

> Please let me know if you're going to require that I fix a bug that
> already exists in the LMB code just to get my NUMA node LMB allocation
> support patch in.

My thought was to put your patch in as-is with another patch to fix
the existing bug either immediately before it or immediately after
it.  I started reading through lmb.c again today but got distracted by
some other things.  It looks like lmb.c could use a bit of a coding
style cleanup, if nothing else.

> Please be straightforward and don't just drop the patch quietly in
> situations like this, let me know what you want to happen in order to
> add the change.

I haven't dropped it, it's just that I haven't got through all of the
patches for .26 yet.

Paul.

^ permalink raw reply

* Kilauea: kernel hangs when using ARCH=powerpc
From: Bernhard Weirich @ 2008-04-07 10:03 UTC (permalink / raw)
  To: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 534 bytes --]

Hello!

When I build the kernel for my kilauea board using ARCH=ppc everything
works fine.
Since ppc is deprecated I'd like to switch to powerpc, but if I do so
the kernel does not produce any output.
There is just the last line of the prompt from the bootloader.
In both cases I built with kilauea_defconfig

I tried the Denx ELDK (4.2) compiler 4.2.2, the toolchain generated by
Buildroot and different kernel versions from the denx repository.
The Kilauea board is Version 1.11b.

Any ideas what is going wrong?

Thanks!
Bernhard


[-- Attachment #2: Type: text/html, Size: 823 bytes --]

^ permalink raw reply

* MVL Linux on MPC8560 Booting goes into infinite loop in early_init memset_io ( )
From: Deepak Gaur @ 2008-04-07  6:49 UTC (permalink / raw)
  To: linuxppc-embedded

Hi all,

While booting MVL linux on MPC8560 based board the kernel goes into a infinite loop in
setup.c. The uncompressed image is located at 0x00000000 and is booted from 0x00000000

arch/ppc/kernel/head_fsl_booke.S
------------------------------------
bl early_init

arch/ppc/kernel/setup.c
----------------------------------------
unsigned long
early_init(int r3, int r4, int r5)
{
        unsigned long phys;
        unsigned long offset = reloc_offset();

        /* Default */
        phys = offset + KERNELBASE;

        /* First zero the BSS -- use memset, some arches don't have
         * caches on yet */
       
        memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);

        __bss_start is 0xc039b00 and __bss_stop = _end =c03c7d90  _end


        Please anyone give me some pointers to understand this i.e use of PTRRELOC and
REASON BEHIND clearing area from __bss_start to _end - __bss_start even though lot of
symbols and functions are defined here(as per System.map)

System.map
---------------------
c039b000 A __bss_start
c039b000 A __chrp_begin
c039b000 A __chrp_end
c039b000 A __init_end
c039b000 A __openfirmware_begin
c039b000 A __openfirmware_end
c039b000 A __pmac_begin
c039b000 A __pmac_end
c039b000 A __prep_begin
c039b000 A __prep_end
c039b000 B system_state
c039b004 B late_time_init
c039b008 b execute_command
c039b00c b panic_later
c039b010 b panic_param
c039b014 B Version_132618
.....
.....

c03c4458 B ic_nameservers
c03c4464 B unix_socket_table
c03c4464 B unix_table_lock
c03c4868 b auth_domain_table
c03c4868 b authtab_lock
c03c4868 b packet_sklist_lock
c03c4868 b rpc_credcache_lock
c03c4868 b rpc_queue_lock
c03c4868 b rpc_sched_lock
c03c4968 b ip_table
c03c4d68 b pmap_lock
c03c4d68 b pmap_stats
c03c4d90 b cache_defer_hash
c03c4d90 b cache_defer_lock
c03c4d90 b cache_list_lock
c03c4d90 b queue_lock
c03c5d90 b write_buf
c03c7d90 A __bss_stop
c03c7d90 A _end

Thanks,

Deepak Gaur

^ permalink raw reply

* Re:Boot freezes at memset_io in early_init
From: Deepak Gaur @ 2008-04-07  6:37 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 1846 bytes --]

Hi all,

While booting MVL linux on MPC8560 based board the kernel goes into a
infinite loop in setup.c

arch/ppc/kernel/head_fsl_booke.S
------------------------------------
bl early_init

arch/ppc/kernel/setup.c
----------------------------------------
unsigned long
early_init(int r3, int r4, int r5)
{
        unsigned long phys;
        unsigned long offset = reloc_offset();

        /* Default */
        phys = offset + KERNELBASE;

        /* First zero the BSS -- use memset, some arches don't have
         * caches on yet */

        memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);

        __bss_start is 0xc039b00 and __bss_stop = _end =c03c7d90  _end


        Please anyone give me some pointers to understand this i.e use of
PTRRELOC and REASON BEHIND clearing area from __bss_start to _end -
__bss_start even though lot of symbols and functions are defined here(as per
System.map)

System.map
---------------------
c039b000 A __bss_start
c039b000 A __chrp_begin
c039b000 A __chrp_end
c039b000 A __init_end
c039b000 A __openfirmware_begin
c039b000 A __openfirmware_end
c039b000 A __pmac_begin
c039b000 A __pmac_end
c039b000 A __prep_begin
c039b000 A __prep_end
c039b000 B system_state
c039b004 B late_time_init
c039b008 b execute_command
c039b00c b panic_later
c039b010 b panic_param
c039b014 B Version_132618
.....
.....

c03c4458 B ic_nameservers
c03c4464 B unix_socket_table
c03c4464 B unix_table_lock
c03c4868 b auth_domain_table
c03c4868 b authtab_lock
c03c4868 b packet_sklist_lock
c03c4868 b rpc_credcache_lock
c03c4868 b rpc_queue_lock
c03c4868 b rpc_sched_lock
c03c4968 b ip_table
c03c4d68 b pmap_lock
c03c4d68 b pmap_stats
c03c4d90 b cache_defer_hash
c03c4d90 b cache_defer_lock
c03c4d90 b cache_list_lock
c03c4d90 b queue_lock
c03c5d90 b write_buf
c03c7d90 A __bss_stop
c03c7d90 A _end

Thanks,

Deepak Gaur

[-- Attachment #2: Type: text/html, Size: 2446 bytes --]

^ permalink raw reply

* Re: Patches added to powerpc.git powerpc-next and master branches
From: David Miller @ 2008-04-07  6:22 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <18425.46732.651483.504040@cargo.ozlabs.ibm.com>

From: Paul Mackerras <paulus@samba.org>
Date: Mon, 7 Apr 2008 15:52:12 +1000

> The following patches have been added to the master and powerpc-next
> branches of the powerpc.git repository.  There is a bunch that I
> pulled from Josh Boyer's tree plus others that I have committed.

Please let me know if you're going to require that I fix a bug that
already exists in the LMB code just to get my NUMA node LMB allocation
support patch in.

Please be straightforward and don't just drop the patch quietly in
situations like this, let me know what you want to happen in order to
add the change.

^ permalink raw reply

* Re: [PATCH] [POWERPC] Update linker script to properly set physical addresses
From: Paul Mackerras @ 2008-04-07  6:01 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0804030128170.15263@blarg.am.freescale.net>

Kumar Gala writes:

> We can set LOAD_OFFSET and use the AT attribute on sections and the
> linker will properly set the physical address of the LOAD program
> header for us.

Nice...

>  #define KERNELBASE      ASM_CONST(CONFIG_KERNEL_START)
>  #define PAGE_OFFSET	ASM_CONST(CONFIG_PAGE_OFFSET)
> +#define LOAD_OFFSET	ASM_CONST((CONFIG_KERNEL_START-CONFIG_PHYSICAL_START))

I think this should be CONFIG_PAGE_OFFSET - CONFIG_PHYSICAL_START
though.

Paul.

^ permalink raw reply

* Patches added to powerpc.git powerpc-next and master branches
From: Paul Mackerras @ 2008-04-07  5:52 UTC (permalink / raw)
  To: linuxppc-dev

The following patches have been added to the master and powerpc-next
branches of the powerpc.git repository.  There is a bunch that I
pulled from Josh Boyer's tree plus others that I have committed.

Paul.

Grant Likely (2):
      [POWERPC] add target for building .dtb files
      [POWERPC] bootwrapper: Add a firmware-independent simpleboot target.

Ionut Nicu (1):
      [POWERPC] Fix kernel panic in arch_arm_kprobe

Josh Boyer (2):
      [POWERPC] 4xx: Add Canyonlands and Yosemite to multi-board defconfig
      [POWERPC] Add of_device_is_available function

Nathan Lynch (1):
      [POWERPC] Convert pci and eeh code to of_device_is_available

Robert P. J. Day (1):
      [POWERPC] Use __SPIN_LOCK_UNLOCKED macro in mpc52xx_set_psc_clkdiv

Roel Kluin (1):
      [POWERPC] Replace logical-AND by bit-AND in pci_process_ISA_OF_ranges()

Stefan Roese (5):
      [POWERPC] 4xx: Only reset PCIe PHY on 405EX systems when no link is detected
      [POWERPC] 4xx: Fix PESDRn_UTLSET1 register setup on 460EX/GT
      [POWERPC] 4xx: Create common ppc4xx_reset_system() in ppc4xx_soc.c
      [POWERPC] 4xx: Some EMAC related changes in Canyonlands & Glacier dts files
      [POWERPC] 4xx: Change dts files to support jumbo frames

Stephen Neuendorffer (1):
      [POWERPC] of_serial: Fix possible null dereference.

Stephen Rothwell (2):
      [POWERPC] htab_remove_mapping is only used by MEMORY_HOTPLUG
      [POWERPC] Remove CONFIG_PCI_LEGACY from some configs

Steven Rostedt (1):
      [POWERPC] Add hand-coded assembly strcmp

Timur Tabi (1):
      [POWERPC] Enable CONFIG_FORCE_MAX_ZONEORDER for all PowerPC, and make selectable

Valentine Barshak (1):
      [POWERPC] 4xx: Use machine_device_initcall() for warp_nand

^ permalink raw reply

* Re: [PATCH v2] powerpc: Add irqtrace support for 32-bit powerpc
From: Benjamin Herrenschmidt @ 2008-04-07  4:49 UTC (permalink / raw)
  To: Dale Farnsworth; +Cc: linuxppc-dev, Johannes Berg
In-Reply-To: <20080404213932.GA15847@farnsworth.org>

I think I found one:

 .../...

> -	mr	r6,r3
>  	rlwinm	r12,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
>  	/* disable interrupts so current_thread_info()->flags can't change */
>  	LOAD_MSR_KERNEL(r10,MSR_KERNEL)	/* doesn't include MSR_EE */
>  	SYNC
>  	MTMSRD(r10)
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +	stwu	r1,-16(r1)
> +	stw	r3,12(r1)
> +	bl      trace_hardirqs_off
> +	lwz	r3,12(r1)
> +	addi	r1,r1,16
> +	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
> +#endif

Here, r12 is clobbered, though it's used two lines later:

> +	mr	r6,r3
>  	lwz	r9,TI_FLAGS(r12)

Here.

You can probably just move the rlwinm down as you moved the mr.

Note that I've been wondering wether we should attempt to trace all
those IRQ state change internally to the exception code. I've looked at
not doing it, which simplifies things a bit.

Unfortunately, that will make us occasionally trace redundant
enable/disable (which isn't a big problem per-se, just counters).

The idea is that I only kept the trace of disable in transfer_to_handler
and I modified the enable tracing in restore: moved it lower down, and
made it test for _MSR(r1):MSR_EE. I added a trace_irq_off just before
the preempt_schedule_irq() as well.

Anyway, let me know what you think.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH] powerpc - Use KBUILD_CFLAGS and similar
From: Paul Mackerras @ 2008-04-07  3:27 UTC (permalink / raw)
  To: Bastian Blank; +Cc: linuxppc-dev
In-Reply-To: <20080302190632.GA9898@wavehammer.waldi.eu.org>

Bastian Blank writes:

> The attached patch changes the powerpc main Makefile from using the override
> make directive to KBUILD_CFLAGS and similar.

I get build failures on all 64-bit targets with this patch.  It ends
up using both -m32 and -m64 on the gcc command line for assembling .S
files.

Paul.

^ permalink raw reply

* a question about use dtb to bootting linux kernel on MPC83xx platform
From: 旭 罗 @ 2008-04-07  1:35 UTC (permalink / raw)
  To: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 1368 bytes --]

    I am Linux software engineer. These days I was debugging a MPC8313 system. In  the debugging process, some source code in the kernel makes me puzzled. So I  have find your email address in the source code. I think you can give me some  advises to solve the problem.
  
        My version is  linux-2.6.23.9 and I use the device tree(dtb) to  booting the kernel. In my bootloader I use the following code to jump to the  kernel.
 (*image)((bd_t *)dtb_entry,  (unsigned int)image, 0, 0, 0); 
  
 The dtb_entry is the address of dtb  file which in the SDRAM, the image is the kernel entry point. I flashed some  LEDs in my board. So I can make sure the program run to the machine_init() which  is defined in the /arch/powerpc/kernel/setup_32.c
In order to trace the problem I  search the source code. I can find that these information is printed by the  start function which is defined in the /arch/powerpc/boot/main.c.  
 Fourth more I have found that the  kernel call the platform_init which is defined in the  /arch/powerpc/boot/cuboot-83xx.c. looking the file head I have known you are the  author for this file.
 Could you told me how the kernel  call the platform_init function and I hope you can show me the booting process  of the MPC83xx linux or you could give me some document about  it.

       
---------------------------------
 雅虎邮箱,您的终生邮箱!

[-- Attachment #2: Type: text/html, Size: 2892 bytes --]

^ permalink raw reply

* Re: [RFC][PATCH] initial port of fixmap over from x86 for ppc32
From: Benjamin Herrenschmidt @ 2008-04-07  0:43 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, hollisb
In-Reply-To: <18425.24938.332852.315571@cargo.ozlabs.ibm.com>


> You have FIX_PCIE_MCFG in there too (keyed off CONFIG_PCI_MMCONFIG
> which we don't have and don't want to have).  If you need to map in
> PCIe config space, what's wrong with just using ioremap?  Why do you
> need to have a fixed virtual address for it?

Well, that was the whole point for doing the fixmap stuff actually, to
be able to have a non-HIGHMEM version of a quick kmap_atomic for ...
PCIe config space :-)

On some PCIe host brigdes like the ones used on 4xx or FSL chips, the
config space is physically mapped as a large linear space, too large to
ioremap permanently, and we can't ioremap from within the low level
config ops.

So the idea is to use a fixmap as a "window" to the config space,
possibly per-cpu. Ultimately, we should even be able to directly insert
TLB entries in kmap_atomic/fixmap to make it even faster.

> More generally, I think we need to take an overall look at what things
> we are using fixed virtual addresses for, and why they need to be
> fixed.  If there are indeed several such things then we can introduce
> the fixmap stuff.

The virtual address doesn't _need_ to be fixed in our case. It's more
like x86 builds kmap on top of fixmap and we were thinking about doing
the same, having it fixed makes it slightly easier to whack things but I
agree it's not necessarily the best option.

We could instead have something allocated a chunk of virtual space at
boot and provide a quick map/unmap.

But by using fixmap, we can use common code with kmap_atomic quickly and
easily.

Ben.

^ permalink raw reply

* Re: [RFC][PATCH] initial port of fixmap over from x86 for ppc32
From: Paul Mackerras @ 2008-04-06 23:48 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, hollisb
In-Reply-To: <Pine.LNX.4.64.0804030144460.15974@blarg.am.freescale.net>

Kumar Gala writes:

> Wanted to get any feedback on this initial port of the fixmap support over
> from x86.  There are a few TODOs:

I have no objection in principle, but your patch below imports a few
things that aren't (and won't be) needed on powerpc AFAICS -- for
example, we don't need FIX_VDSO, since our VDSO is mapped into user
space at the 1MB point (by default).

You have FIX_PCIE_MCFG in there too (keyed off CONFIG_PCI_MMCONFIG
which we don't have and don't want to have).  If you need to map in
PCIe config space, what's wrong with just using ioremap?  Why do you
need to have a fixed virtual address for it?

More generally, I think we need to take an overall look at what things
we are using fixed virtual addresses for, and why they need to be
fixed.  If there are indeed several such things then we can introduce
the fixmap stuff.

Paul.

^ permalink raw reply

* [PATCH] make help: Show defconfig subdirs
From: Segher Boessenkool @ 2008-04-06 20:16 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev; +Cc: Sam Ravnborg

PowerPC will start moving board defconfigs into subarch-specific
subdirs soon.  "make help" currently does not look in subdirs to
find the defconfigs to show.  This is partially a good thing,
since there are way too many defconfigs for one list.

This patch makes the main "make help" display something like

  help-40x         - Show 40x-specific targets
  help-44x         - Show 44x-specific targets
  help-boards      - Show all of the above

and wires up stuff so those new help-* commands actually work.

Cc: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Cc: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Segher Boessenkool <segher@kernel.crashing.org>
---
 Makefile |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile
index fec2a12..05d9fda 100644
--- a/Makefile
+++ b/Makefile
@@ -1172,6 +1172,8 @@ rpm: include/config/kernel.release FORCE
 
 boards := $(wildcard $(srctree)/arch/$(ARCH)/configs/*_defconfig)
 boards := $(notdir $(boards))
+board-dirs := $(dir $(wildcard $(srctree)/arch/$(ARCH)/configs/*/*_defconfig))
+board-dirs := $(sort $(notdir $(board-dirs:/=)))
 
 help:
 	@echo  'Cleaning targets:'
@@ -1225,6 +1227,11 @@ help:
 		$(foreach b, $(boards), \
 		printf "  %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \
 		echo '')
+	@$(if $(board-dirs), \
+		$(foreach b, $(board-dirs), \
+		printf "  %-16s - Show %s-specific targets\\n" help-$(b) $(b);) \
+		printf "  %-16s - Show all of the above\\n" help-boards; \
+		echo '')
 
 	@echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
 	@echo  '  make V=2   [targets] 2 => give reason for rebuild of target'
@@ -1236,6 +1243,20 @@ help:
 	@echo  'For further info see the ./README file'
 
 
+help-board-dirs := $(addprefix help-,$(board-dirs))
+
+help-boards: $(help-board-dirs)
+
+boards-per-dir = $(notdir $(wildcard $(srctree)/arch/$(ARCH)/configs/$*/*_defconfig))
+
+$(help-board-dirs): help-%:
+	@echo  'Architecture specific targets ($(ARCH) $*):'
+	@$(if $(boards-per-dir), \
+		$(foreach b, $(boards-per-dir), \
+		printf "  %-24s - Build for %s\\n" $*/$(b) $(subst _defconfig,,$(b));) \
+		echo '')
+
+
 # Documentation targets
 # ---------------------------------------------------------------------------
 %docs: scripts_basic FORCE
-- 
1.5.3.4.208.g805a

^ permalink raw reply related

* Re: [PATCH RFC] tqm8560.dts: add local bus devices
From: Wolfgang Grandegger @ 2008-04-06 18:45 UTC (permalink / raw)
  Cc: ppc-dev
In-Reply-To: <47F90B97.4080904@grandegger.com>

Wolfgang Grandegger wrote:
> Segher Boessenkool wrote:
>>> +                        partition@300000 {
>>> +                                label = "fs";
>>> +                                reg = <0x00300000 0x07c00000>;
>>> +                        };
>>> +                        partition@7700000 {
>>> +                                label = "firmware";
>>> +                                reg = <0x07700000 0x00100000>;
>> These two overlap; should the latter be @7f00000?
> 
> Yes, of course.
> 
>>> +        can@2,0 {
>>> +            device_type = "can";
>> No device_type please.
> 
> OK, but then I better use a more descriptive name for the compatible
> property, e.g.:
> 
> 	compatible = "can-i82527";	// Intel 82527 or Bosch CC770
> 
>>> +        nand@3,0 {
>>> +            #address-cells = <1>;
>>> +            #size-cells = <1>;
>>> +            compatible = "fsl,mpc8560-fcm-nand",
>>> +                         "fsl,elbc-fcm-nand";
>>> +            reg = <0x3 0x0 0x8000>;
>>> +
>>> +            kernel@0 {
>>> +                                label = "kernel";
>>> +                reg = <0x000000 0x0300000>;
>>> +            };
>>> +            fs@300000 {
>>> +                                label = "fs";
>>> +                reg = <0x300000 0x7d00000>;
>>> +            };
>>> +        };
>>> +    };
>> There should be a node that describes the nand chip between the nand
>> controller node and the partition nodes.
> 
> I took the mpc8378_*.dts files of 2.6.25-rc8 as example and there is no
> such node. Could you point me please to a more appropriate example.

In the meantime I realized, that the upcoming FSL UPM driver seems to be
appropriate for that board:

  http://ozlabs.org/pipermail/linuxppc-dev/2008-March/052890.html

What is the status of this driver? Are there already some boards using
it (including DTS file)?

Wolfgang.

^ permalink raw reply

* Re: [PATCH RFC] tqm8560.dts: add local bus devices
From: Wolfgang Grandegger @ 2008-04-06 17:42 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: ppc-dev
In-Reply-To: <0d57d42da9d29cc240be9d38de29ed96@kernel.crashing.org>

Segher Boessenkool wrote:
>> +                        partition@300000 {
>> +                                label = "fs";
>> +                                reg = <0x00300000 0x07c00000>;
>> +                        };
>> +                        partition@7700000 {
>> +                                label = "firmware";
>> +                                reg = <0x07700000 0x00100000>;
> 
> These two overlap; should the latter be @7f00000?

Yes, of course.

> 
>> +        can@2,0 {
>> +            device_type = "can";
> 
> No device_type please.

OK, but then I better use a more descriptive name for the compatible
property, e.g.:

	compatible = "can-i82527";	// Intel 82527 or Bosch CC770

> 
>> +        nand@3,0 {
>> +            #address-cells = <1>;
>> +            #size-cells = <1>;
>> +            compatible = "fsl,mpc8560-fcm-nand",
>> +                         "fsl,elbc-fcm-nand";
>> +            reg = <0x3 0x0 0x8000>;
>> +
>> +            kernel@0 {
>> +                                label = "kernel";
>> +                reg = <0x000000 0x0300000>;
>> +            };
>> +            fs@300000 {
>> +                                label = "fs";
>> +                reg = <0x300000 0x7d00000>;
>> +            };
>> +        };
>> +    };
> 
> There should be a node that describes the nand chip between the nand
> controller node and the partition nodes.

I took the mpc8378_*.dts files of 2.6.25-rc8 as example and there is no
such node. Could you point me please to a more appropriate example.

> 
>> Do these entries make sense?
> 
> Looks good otherwise :-)

Thanks.

Wolfgang.

^ permalink raw reply

* Re: 4xx defconfig reorg
From: Segher Boessenkool @ 2008-04-06 15:32 UTC (permalink / raw)
  To: jwboyer; +Cc: linuxppc-dev, paulus
In-Reply-To: <1207487181.6809.18.camel@vader.jdub.homelinux.org>

> Unless someone screams loudly and has reasons why this shouldn't go in,

These configs won't show up for "make help" anymore, which of course is
nice because that list was too long, but we need a way to get that back
since it was useful.  I'll see what I can do.


Segher

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox