All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] ps3av/fb drivers for 2.6.21
@ 2007-01-25 17:46 Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                   ` (9 more replies)
  0 siblings, 10 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:46 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

	Hi James, Paul,

This is the first submission of the PS3 AV Settings Driver and the PS3 Virtual
Frame Buffer Driver.

To ease the review, I'm sending all patches to both relevant maintaines and
mailing lists.

[PATCH 1/9] ps3: AV Settings Driver
[PATCH 2/9] fbdev modedb: allow refresh rates for named video modes
[PATCH 3/9] fbdev modedb: make more pointer parameters const
[PATCH 4/9] fb_videomode_to_var: reset virtual screen parameters
[PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
[PATCH 6/9] ps3: Virtual Frame Buffer Driver
[PATCH 7/9] ps3: disable display flipping during mode changes
[PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
[PATCH 9/9] ps3: ps3av/fb defconfig updates

PowerPC-specific patches (1, 5, 7, 8 and 9) apply on top of the patches sent
by Geoff Levand to linuxppc-dev yesterday.
Frame buffer specific-patches (2, 3, 4, and 6) apply on Linus' current tree.

Please review. All comments are welcome.
Our goal is to get these drivers integrated into 2.6.21.

Thanks!

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 1/9] ps3: AV Settings Driver
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:48   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:48 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

Add the PS3 AV Settings Driver.

The AV Settings driver is used to control Audio and Video settings.
It communicates with the policy manager through the virtual uart.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 arch/powerpc/platforms/ps3/Kconfig |   10 
 drivers/ps3/Makefile               |    1 
 drivers/ps3/ps3av.c                |  998 +++++++++++++++++++++++++++++++++++
 drivers/ps3/ps3av_cmd.c            | 1052 +++++++++++++++++++++++++++++++++++++
 include/asm-powerpc/ps3av.h        |  716 +++++++++++++++++++++++++
 5 files changed, 2777 insertions(+)

--- ps3-linux.orig/arch/powerpc/platforms/ps3/Kconfig
+++ ps3-linux/arch/powerpc/platforms/ps3/Kconfig
@@ -51,4 +51,14 @@ config PS3_VUART
 	  including the System Manager and AV Settings.  In
 	  general, all users will say Y.
 
+config PS3_PS3AV
+	tristate "PS3 AV controller support"
+	default y
+	depends on PS3_VUART
+	help
+	  Include support for the PS3 Platform AV Settings device.
+
+	  This support is required for graphics and sound. In
+	  general, all users will say Y or M.
+
 endmenu
--- ps3-linux.orig/drivers/ps3/Makefile
+++ ps3-linux/drivers/ps3/Makefile
@@ -1,2 +1,3 @@
 obj-y += system-bus.o
 obj-$(CONFIG_PS3_VUART) += vuart.o
+obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
--- /dev/null
+++ ps3-linux/drivers/ps3/ps3av.c
@@ -0,0 +1,998 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ * AV backend support for PS3
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/kernel.h>
+#include <linux/ioctl.h>
+#include <linux/mutex.h>
+#include <asm/lv1call.h>
+#include <asm/atomic.h>
+#include <asm/ps3av.h>
+#include <asm/ps3.h>
+
+#include "vuart.h"
+
+#ifdef PS3AV_DEBUG
+#define DPRINTK(fmt, args...) \
+	do { printk("ps3av " fmt, ## args); } while (0)
+#else
+#define DPRINTK(fmt, args...) do { } while (0)
+#endif
+
+#define BUFSIZE          4096	/* vuart buf size */
+#define PS3AV_BUF_SIZE   512	/* max packet size */
+
+static int timeout = 5000;	/* in msec ( 5 sec ) */
+module_param(timeout, int, 0644);
+
+static struct ps3av ps3av;
+
+static DEFINE_MUTEX(ps3av_mutex);
+static int ps3av_open_count = 0;
+
+/* color space */
+#define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
+#define RGB8   PS3AV_CMD_VIDEO_CS_RGB_8
+/* format */
+#define XRGB   PS3AV_CMD_VIDEO_FMT_X8R8G8B8
+/* aspect */
+#define A_N    PS3AV_CMD_AV_ASPECT_4_3
+#define A_W    PS3AV_CMD_AV_ASPECT_16_9
+static const struct avset_video_mode {
+	u32 cs;
+	u32 fmt;
+	u32 vid;
+	u32 aspect;
+	u32 x;
+	u32 y;
+	u32 interlace;
+	u32 freq;
+} video_mode_table[] = {
+	{     0, }, /* auto */
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I,       A_N,  720,  480, 1, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P,       A_N,  720,  480, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ,  A_N, 1280,  720, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I,       A_N,  720,  576, 1, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P,       A_N,  720,  576, 0, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ,  A_N, 1280,  720, 0, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA,       A_W, 1280,  768, 0, 60},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA,       A_N, 1280, 1024, 0, 60},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA,      A_W, 1920, 1200, 0, 60},
+};
+
+/* supported CIDs */
+static u32 cmd_table[] = {
+	/* init */
+	PS3AV_CID_AV_INIT,
+	PS3AV_CID_AV_FIN,
+	PS3AV_CID_VIDEO_INIT,
+	PS3AV_CID_AUDIO_INIT,
+
+	/* set */
+	PS3AV_CID_AV_ENABLE_EVENT,
+	PS3AV_CID_AV_DISABLE_EVENT,
+
+	PS3AV_CID_AV_VIDEO_CS,
+	PS3AV_CID_AV_VIDEO_MUTE,
+	PS3AV_CID_AV_VIDEO_DISABLE_SIG,
+	PS3AV_CID_AV_AUDIO_PARAM,
+	PS3AV_CID_AV_AUDIO_MUTE,
+	PS3AV_CID_AV_HDMI_MODE,
+	PS3AV_CID_AV_TV_MUTE,
+
+	PS3AV_CID_VIDEO_MODE,
+	PS3AV_CID_VIDEO_FORMAT,
+	PS3AV_CID_VIDEO_PITCH,
+
+	PS3AV_CID_AUDIO_MODE,
+	PS3AV_CID_AUDIO_MUTE,
+	PS3AV_CID_AUDIO_ACTIVE,
+	PS3AV_CID_AUDIO_INACTIVE,
+	PS3AV_CID_AVB_PARAM,
+
+	/* get */
+	PS3AV_CID_AV_GET_HW_CONF,
+	PS3AV_CID_AV_GET_MONITOR_INFO,
+
+	/* event */
+	PS3AV_CID_EVENT_UNPLUGGED,
+	PS3AV_CID_EVENT_PLUGGED,
+	PS3AV_CID_EVENT_HDCP_DONE,
+	PS3AV_CID_EVENT_HDCP_FAIL,
+	PS3AV_CID_EVENT_HDCP_AUTH,
+	PS3AV_CID_EVENT_HDCP_ERROR,
+
+	0
+};
+
+#define PS3AV_EVENT_CMD_MASK           0x10000000
+#define PS3AV_EVENT_ID_MASK            0x0000ffff
+#define PS3AV_CID_MASK                 0xffffffff
+#define PS3AV_REPLY_BIT                0x80000000
+
+#define ps3av_event_get_port_id(cid)   ((cid >> 16) & 0xff)
+
+static u32 *ps3av_search_cmd_table(u32 cid, u32 mask)
+{
+	u32 *table;
+	int i;
+
+	table = cmd_table;
+	for (i = 0;; table++, i++) {
+		if ((*table & mask) == (cid & mask))
+			break;
+		if (*table == 0)
+			return NULL;
+	}
+	return table;
+}
+
+static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
+{
+	u32 *table;
+
+	if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
+		table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
+		if (table)
+			DPRINTK
+			    ("recv event packet cid:%08x port:0x%x size:%d\n",
+			     hdr->cid, ps3av_event_get_port_id(hdr->cid),
+			     hdr->size);
+		else
+			printk(KERN_ERR
+			       "%s: failed event packet, cid:%08x size:%d\n",
+			       __FUNCTION__, hdr->cid, hdr->size);
+		return 1;	/* receive event packet */
+	}
+	return 0;
+}
+
+static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
+			      struct ps3av_reply_hdr *recv_buf, int write_len,
+			      int read_len)
+{
+	int res;
+	u32 cmd;
+	int event;
+
+	if (!ps3av.available)
+		return -ENODEV;
+
+	/* send pkt */
+	res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
+	if (res < 0) {
+		DPRINTK("%s: ps3av_vuart_write() failed (result=%d)\n",
+			__FUNCTION__, res);
+		return res;
+	}
+
+	/* recv pkt */
+	cmd = send_buf->cid;
+	do {
+		/* read header */
+		res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
+				       timeout);
+		if (res != PS3AV_HDR_SIZE) {
+			DPRINTK("%s: ps3av_vuart_read() failed (result=%d)\n",
+				__FUNCTION__, res);
+			return res;
+		}
+
+		/* read body */
+		res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
+				       recv_buf->size, timeout);
+		if (res < 0) {
+			DPRINTK("%s: ps3av_vuart_read() failed (result=%d)\n",
+				__FUNCTION__, res);
+			return res;
+		}
+		res += PS3AV_HDR_SIZE;	/* total len */
+		event = ps3av_parse_event_packet(recv_buf);
+		/* ret > 0 event packet */
+	} while (event);
+
+	if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
+		DPRINTK("%s: reply err (result=%x)\n",
+			__FUNCTION__, recv_buf->cid);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf,
+				      const struct ps3av_reply_hdr *recv_buf,
+				      int user_buf_size)
+{
+	int return_len;
+
+	if (recv_buf->version != PS3AV_VERSION) {
+		DPRINTK("reply_packet invalid version:%x\n",
+			recv_buf->version);
+		return -EFAULT;
+	}
+	return_len = recv_buf->size + PS3AV_HDR_SIZE;
+	if (return_len > user_buf_size)
+		return_len = user_buf_size;
+	memcpy(cmd_buf, recv_buf, return_len);
+	return 0;		/* success */
+}
+
+void ps3av_set_hdr(u32 cid, u16 size, struct ps3av_send_hdr *hdr)
+{
+	hdr->version = PS3AV_VERSION;
+	hdr->size = size - PS3AV_HDR_SIZE;
+	hdr->cid = cid;
+}
+
+int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
+		 struct ps3av_send_hdr *buf)
+{
+	int res = 0;
+	union {
+		struct ps3av_reply_hdr reply_hdr;
+		u8 raw[PS3AV_BUF_SIZE];
+	} recv_buf;
+
+	u32 *table;
+
+	BUG_ON(!ps3av.available);
+
+	if (down_interruptible(&ps3av.sem)) {
+		printk(KERN_ERR "%s:sem failed cid:%x \n", __FUNCTION__, cid);
+		return -ERESTARTSYS;
+	}
+
+	table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
+	if (table == NULL) {
+		printk(KERN_ERR "%s: invalid_cid:%x\n", __FUNCTION__, cid);
+		res = -EINVAL;
+		goto err;
+	}
+	if (send_len < PS3AV_HDR_SIZE) {
+		printk(KERN_ERR "%s: invalid send_len:%d\n", __FUNCTION__,
+		       send_len);
+		goto err;
+	}
+
+	/* create header */
+	ps3av_set_hdr(cid, send_len, buf);
+
+	if (usr_buf_size < send_len || usr_buf_size > PS3AV_BUF_SIZE) {
+		printk(KERN_ERR "%s: invalid packet size:%ld\n", __FUNCTION__,
+		       usr_buf_size);
+		goto err;
+	}
+
+	/* send packet via vuart */
+	res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
+				 usr_buf_size);
+	if (res < 0) {
+		printk(KERN_ERR
+		       "%s: ps3av_send_cmd_pkt() failed (result=%d)\n",
+		       __FUNCTION__, res);
+		goto err;
+	}
+
+	/* process reply packet */
+	res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
+					 usr_buf_size);
+	if (res < 0) {
+		printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
+		       __FUNCTION__, res);
+		goto err;
+	}
+
+	up(&ps3av.sem);
+	return 0;
+
+      err:
+	up(&ps3av.sem);
+	printk(KERN_ERR "%s: failed cid:%x res:%d\n", __FUNCTION__, cid, res);
+	return res;
+}
+
+static int ps3av_set_av_video_mute(u32 mute)
+{
+	int i, num_of_av_port, res;
+
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi
+	    + ps3av.av_hw_conf.num_of_avmulti;
+	/* video mute on */
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int ps3av_set_video_disable_sig(u32 id)
+{
+	int i, num_of_hdmi_port, num_of_av_port, res;
+
+	num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+	    ps3av.av_hw_conf.num_of_avmulti;
+
+	/* tv mute */
+	for (i = 0; i < num_of_hdmi_port; i++) {
+		res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+					   PS3AV_CMD_MUTE_ON);
+		if (res < 0)
+			return -1;
+	}
+	msleep(100);
+
+	/* video mute on */
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
+		if (res < 0)
+			return -1;
+		if (i < num_of_hdmi_port) {
+			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+						   PS3AV_CMD_MUTE_OFF);
+			if (res < 0)
+				return -1;
+		}
+	}
+	msleep(300);
+
+	return 0;
+}
+
+static int ps3av_set_audio_mute(u32 mute)
+{
+	int i, num_of_av_port, num_of_opt_port, res;
+
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+	    ps3av.av_hw_conf.num_of_avmulti;
+	num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
+
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+	for (i = 0; i < num_of_opt_port; i++) {
+		res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
+{
+	struct ps3av_pkt_avb_param avb_param;
+	int i, num_of_audio, vid, res;
+	struct ps3av_pkt_audio_mode audio_mode;
+	u8 *param_p;
+	u32 len;
+
+	num_of_audio = ps3av.av_hw_conf.num_of_hdmi
+	    + ps3av.av_hw_conf.num_of_avmulti + ps3av.av_hw_conf.num_of_spdif;
+
+	avb_param.num_of_video_pkt = 0;
+	avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO;	/* allways 0 */
+	avb_param.num_of_av_video_pkt = 0;
+	avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
+
+	vid = video_mode_table[atomic_read(&ps3av.ps3av_mode)].vid;
+
+	/* audio mute */
+	ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
+
+	/* audio inactive */
+	res = ps3av_cmd_audio_active(0, ps3av.audio_port);
+	if (res < 0)
+		DPRINTK("ps3av_cmd_audio_active OFF failed\n");
+
+	param_p = (u8 *) &avb_param.video;
+	/* audio_pkt */
+	for (i = 0; i < num_of_audio; i++) {
+		ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
+					 word_bits, format, source);
+		if (i < ps3av.av_hw_conf.num_of_hdmi) {
+			/* hdmi only */
+			param_p = ps3av_cmd_set_av_audio_param(param_p,
+							       ps3av.av_port[i],
+							       &audio_mode,
+							       vid);
+		}
+		/* audio_mode pkt should be sent separately */
+		res = ps3av_cmd_audio_mode(&audio_mode);
+		if (res < 0)
+			DPRINTK("ps3av_cmd_audio_mode failed, port:%x\n", i);
+	}
+
+	/* send command using avb pkt */
+	len = param_p - (u8 *) & avb_param;
+	res = ps3av_cmd_avb_param(&avb_param, len);
+	if (res < 0)
+		DPRINTK("ps3av_cmd_avb_param failed\n");
+
+	/* audio mute */
+	ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
+
+	/* audio active */
+	res = ps3av_cmd_audio_active(1, ps3av.audio_port);
+	if (res < 0)
+		DPRINTK("ps3av_cmd_audio_active ON failed\n");
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3av_set_audio_mode);
+
+static int ps3av_set_videomode(u32 id)
+{
+	struct ps3av_pkt_avb_param avb_param;
+	int i;
+	u8 *param_p;
+	u32 len, av_video_cs = 0;
+	const struct avset_video_mode *video_mode;
+	int old_mode, res, event = 0;
+
+	old_mode = ps3av_get_mode();
+
+	video_mode = &video_mode_table[id & PS3AV_MODE_MASK];
+
+	avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO;	/* num of head */
+	avb_param.num_of_audio_pkt = 0;
+	avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
+	    ps3av.av_hw_conf.num_of_avmulti;
+	avb_param.num_of_av_audio_pkt = 0;
+
+	/* send command packet */
+	if (event) {
+		/* event enable */
+		res = ps3av_cmd_enable_event();
+		if (res < 0)
+			DPRINTK("ps3av_cmd_enable_event failed \n");
+	}
+
+	/* av video mute */
+	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
+	/* video signal off */
+	ps3av_set_video_disable_sig(id);
+
+	/* Retail PS3 product doesn't support this */
+	if (id & PS3AV_MODE_HDCP_OFF) {
+		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
+		if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+			DPRINTK("Not supported\n");
+		else if (res)
+			DPRINTK("ps3av_cmd_av_hdmi_mode failed\n");
+	} else if (old_mode & PS3AV_MODE_HDCP_OFF) {
+		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
+		if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+			DPRINTK("ps3av_cmd_av_hdmi_mode failed\n");
+	}
+
+	param_p = (u8 *) & avb_param.video;
+	/* video_pkt */
+	for (i = 0; i < avb_param.num_of_video_pkt; i++)
+		param_p = ps3av_cmd_set_video_mode(param_p,
+						   ps3av.head[i],
+						   video_mode->vid,
+						   video_mode->fmt, id);
+	/* av_video_pkt */
+	for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
+		if (id & PS3AV_MODE_DVI || id & PS3AV_MODE_RGB)
+			av_video_cs = RGB8;
+		else
+			av_video_cs = video_mode->cs;
+#ifndef PS3AV_HDMI_YUV
+		if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
+		    ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
+			av_video_cs = RGB8;	/* use RGB for HDMI */
+#endif
+		param_p = ps3av_cmd_set_av_video_cs(param_p, ps3av.av_port[i],
+						    video_mode->vid,
+						    av_video_cs,
+						    video_mode->aspect, id);
+	}
+	/* send command using avb pkt */
+	len = param_p - (u8 *) & avb_param;
+	res = ps3av_cmd_avb_param(&avb_param, len);
+	if (res == PS3AV_STATUS_NO_SYNC_HEAD)
+		printk(KERN_WARNING
+		       "%s: Command failed. Please try your request again. \n",
+		       __FUNCTION__);
+	else if (res)
+		DPRINTK("ps3av_cmd_avb_param failed\n");
+
+	msleep(1500);
+	/* av video mute */
+	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);
+
+	return 0;
+}
+
+static int ps3av_vid2table_id(int vid)
+{
+	int i;
+
+	for (i = 1; i < ARRAY_SIZE(video_mode_table); i++)
+		if (video_mode_table[i].vid == vid)
+			return i;
+	return -1;
+}
+
+static int ps3av_resbit2vid(u32 res_50, u32 res_60)
+{
+	int vid = -1;
+
+	if (res_50 > res_60) {	/* if res_50 == res_60, res_60 will be used */
+		if (res_50 & PS3AV_RESBIT_1920x1080P)
+			vid = PS3AV_CMD_VIDEO_VID_1080P_50HZ;
+		else if (res_50 & PS3AV_RESBIT_1920x1080I)
+			vid = PS3AV_CMD_VIDEO_VID_1080I_50HZ;
+		else if (res_50 & PS3AV_RESBIT_1280x720P)
+			vid = PS3AV_CMD_VIDEO_VID_720P_50HZ;
+		else if (res_50 & PS3AV_RESBIT_720x576P)
+			vid = PS3AV_CMD_VIDEO_VID_576P;
+		else
+			vid = -1;
+	} else {
+		if (res_60 & PS3AV_RESBIT_1920x1080P)
+			vid = PS3AV_CMD_VIDEO_VID_1080P_60HZ;
+		else if (res_60 & PS3AV_RESBIT_1920x1080I)
+			vid = PS3AV_CMD_VIDEO_VID_1080I_60HZ;
+		else if (res_60 & PS3AV_RESBIT_1280x720P)
+			vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+		else if (res_60 & PS3AV_RESBIT_720x480P)
+			vid = PS3AV_CMD_VIDEO_VID_480P;
+		else
+			vid = -1;
+	}
+	return vid;
+}
+
+static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info)
+{
+	u32 res_50, res_60;
+	int vid = -1;
+
+	if (info->monitor_type != PS3AV_MONITOR_TYPE_HDMI)
+		return -1;
+
+	/* check native resolution */
+	res_50 = info->res_50.native & PS3AV_RES_MASK_50;
+	res_60 = info->res_60.native & PS3AV_RES_MASK_60;
+	if (res_50 || res_60) {
+		vid = ps3av_resbit2vid(res_50, res_60);
+		return vid;
+	}
+
+	/* check resolution */
+	res_50 = info->res_50.res_bits & PS3AV_RES_MASK_50;
+	res_60 = info->res_60.res_bits & PS3AV_RES_MASK_60;
+	if (res_50 || res_60) {
+		vid = ps3av_resbit2vid(res_50, res_60);
+		return vid;
+	}
+
+	if (ps3av.region & PS3AV_REGION_60)
+		vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+	else
+		vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+	return vid;
+}
+
+static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf,
+				int boot)
+{
+	int i, res, vid = -1, dvi = 0, rgb = 0;
+	struct ps3av_pkt_av_get_monitor_info monitor_info;
+	struct ps3av_info_monitor *info;
+
+	/* get vid for hdmi */
+	for (i = 0; i < av_hw_conf->num_of_hdmi; i++) {
+		res = ps3av_cmd_video_get_monitor_info(&monitor_info,
+						       PS3AV_CMD_AVPORT_HDMI_0 +
+						       i);
+		if (res < 0)
+			return -1;
+
+#ifdef PS3AV_DEBUG
+		ps3av_cmd_av_monitor_info_dump(&monitor_info);
+#endif
+		info = &monitor_info.info;
+		/* check DVI */
+		if (info->monitor_type == PS3AV_MONITOR_TYPE_DVI) {
+			dvi = PS3AV_MODE_DVI;
+			break;
+		}
+		/* check HDMI */
+		vid = ps3av_hdmi_get_vid(info);
+		if (vid != -1) {
+			/* got valid vid */
+			break;
+		}
+	}
+
+	if (dvi) {
+		/* DVI mode */
+		vid = PS3AV_DEFAULT_DVI_VID;
+	} else if (vid == -1) {
+		/* no HDMI interface or HDMI is off */
+		if (ps3av.region & PS3AV_REGION_60)
+			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
+		else
+			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
+		if (ps3av.region & PS3AV_REGION_RGB)
+			rgb = PS3AV_MODE_RGB;
+	} else if (boot) {
+		/* HDMI: using DEFAULT HDMI_VID while booting up */
+		info = &monitor_info.info;
+		if (ps3av.region & PS3AV_REGION_60) {
+			if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			else {
+				/* default */
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			}
+		} else {
+			if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			else if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			else {
+				/* default */
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			}
+		}
+	}
+
+	return (ps3av_vid2table_id(vid) | dvi | rgb);
+}
+
+static int ps3av_get_hw_conf(struct ps3av *ps3av)
+{
+	int i, j, k, res;
+
+	/* get av_hw_conf */
+	res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf);
+	if (res < 0)
+		return -1;
+
+#ifdef PS3AV_DEBUG
+	ps3av_cmd_av_hw_conf_dump(&ps3av->av_hw_conf);
+#endif
+
+	for (i = 0; i < PS3AV_HEAD_MAX; i++)
+		ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i;
+	for (i = 0; i < PS3AV_OPT_PORT_MAX; i++)
+		ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i;
+	for (i = 0; i < ps3av->av_hw_conf.num_of_hdmi; i++)
+		ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i;
+	for (j = 0; j < ps3av->av_hw_conf.num_of_avmulti; j++)
+		ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j;
+	for (k = 0; k < ps3av->av_hw_conf.num_of_spdif; k++)
+		ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k;
+
+	/* set all audio port */
+	ps3av->audio_port = PS3AV_CMD_AUDIO_PORT_HDMI_0
+	    | PS3AV_CMD_AUDIO_PORT_HDMI_1
+	    | PS3AV_CMD_AUDIO_PORT_AVMULTI_0
+	    | PS3AV_CMD_AUDIO_PORT_SPDIF_0 | PS3AV_CMD_AUDIO_PORT_SPDIF_1;
+
+	return 0;
+}
+
+/* set mode using id */
+int ps3av_set_video_mode(u32 id, int boot)
+{
+	int size;
+	u32 option;
+	u32 old_id;
+
+	size = ARRAY_SIZE(video_mode_table);
+	if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
+		DPRINTK("%s: error id :%d\n", __FUNCTION__, id);
+		return -1;
+	}
+
+	/* auto mode */
+	option = id & ~PS3AV_MODE_MASK;
+	if ((id & PS3AV_MODE_MASK) == 0) {
+		id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+		if (id < 1) {
+			printk(KERN_ERR "%s: invalid id :%d\n", __FUNCTION__,
+			       id);
+			return -1;
+		}
+		id |= option;
+	}
+
+	/* set videomode */
+	old_id = atomic_read(&ps3av.ps3av_mode);
+	atomic_set(&ps3av.ps3av_mode, id);
+	if (ps3av_set_videomode(id))
+		atomic_set(&ps3av.ps3av_mode, old_id);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3av_set_video_mode);
+
+int ps3av_set_mode(u32 id, int boot)
+{
+	int res;
+
+	res = ps3av_set_video_mode(id, boot);
+	if (res)
+		return -1;
+
+	res = ps3av_set_audio_mode(PS3AV_CMD_AUDIO_NUM_OF_CH_2,
+				   PS3AV_CMD_AUDIO_FS_48K,
+				   PS3AV_CMD_AUDIO_WORD_BITS_16,
+				   PS3AV_CMD_AUDIO_FORMAT_PCM,
+				   PS3AV_CMD_AUDIO_SOURCE_SERIAL);
+	if (res)
+		return -1;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3av_set_mode);
+
+int ps3av_get_mode(void)
+{
+	return atomic_read(&ps3av.ps3av_mode);
+}
+
+EXPORT_SYMBOL(ps3av_get_mode);
+
+int ps3av_get_scanmode(int id)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -1;
+	}
+	return video_mode_table[id].interlace;
+}
+
+EXPORT_SYMBOL(ps3av_get_scanmode);
+
+int ps3av_get_refresh_rate(int id)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -1;
+	}
+	return video_mode_table[id].freq;
+}
+
+EXPORT_SYMBOL(ps3av_get_refresh_rate);
+
+/* get resolution by video_mode */
+int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -1;
+	}
+	*xres = video_mode_table[id].x;
+	*yres = video_mode_table[id].y;
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3av_video_mode2res);
+
+/* mute */
+int ps3av_video_mute(int mute)
+{
+	return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON
+					    : PS3AV_CMD_MUTE_OFF);
+}
+
+EXPORT_SYMBOL(ps3av_video_mute);
+
+int ps3av_audio_mute(int mute)
+{
+	return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
+					 : PS3AV_CMD_MUTE_OFF);
+}
+
+EXPORT_SYMBOL(ps3av_audio_mute);
+
+int ps3av_dev_open(void)
+{
+	int status = 0;
+
+	mutex_lock(&ps3av_mutex);
+	if (!ps3av_open_count++) {
+		status = lv1_gpu_open(0);
+		if (status) {
+			printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
+			       __FUNCTION__, status);
+			ps3av_open_count--;
+		}
+	}
+	mutex_unlock(&ps3av_mutex);
+
+	return status;
+}
+
+EXPORT_SYMBOL(ps3av_dev_open);
+
+int ps3av_dev_close(void)
+{
+	int status = 0;
+
+	mutex_lock(&ps3av_mutex);
+	if (ps3av_open_count <= 0) {
+		printk(KERN_ERR "%s: GPU already closed\n", __FUNCTION__);
+		status = -1;
+	} else if (!--ps3av_open_count) {
+		status = lv1_gpu_close();
+		if (status)
+			printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
+			       __FUNCTION__, status);
+	}
+	mutex_unlock(&ps3av_mutex);
+
+	return status;
+}
+
+EXPORT_SYMBOL(ps3av_dev_close);
+
+static int ps3av_at_exit(struct notifier_block *self,
+			 unsigned long state, void *data)
+{
+	/* fin avsetting modules */
+	ps3av_cmd_fin();
+
+	if (!ps3av.available)
+		return NOTIFY_OK;
+
+	ps3av.available = 0;
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block ps3av_reboot_nb = {
+	.notifier_call = ps3av_at_exit
+};
+
+static int ps3av_probe(struct ps3_vuart_port_device *dev)
+{
+	int res;
+	u32 id;
+
+	DPRINTK("init ...\n");
+	DPRINTK("  timeout=%d\n", timeout);
+
+	memset(&ps3av, 0, sizeof(ps3av));
+
+	init_MUTEX(&ps3av.sem);
+	atomic_set(&ps3av.ps3av_mode, 0);
+	ps3av.dev = dev;
+
+	ps3av.available = 1;
+	switch (ps3_os_area_get_av_multi_out()) {
+	case PS3_PARAM_AV_MULTI_OUT_NTSC:
+		ps3av.region = PS3AV_REGION_60;
+		break;
+	case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
+	case PS3_PARAM_AV_MULTI_OUT_SECAM:
+		ps3av.region = PS3AV_REGION_50;
+		break;
+	case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
+		ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
+		break;
+	default:
+		ps3av.region = PS3AV_REGION_60;
+		break;
+	}
+	register_reboot_notifier(&ps3av_reboot_nb);
+
+	/* init avsetting modules */
+	res = ps3av_cmd_init();
+	if (res < 0)
+		printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __FUNCTION__,
+		       res);
+
+	ps3av_get_hw_conf(&ps3av);
+	id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
+	atomic_set(&ps3av.ps3av_mode, id);
+
+	DPRINTK("init...done\n");
+
+	return 0;
+}
+
+static int ps3av_remove(struct ps3_vuart_port_device *dev)
+{
+	if (ps3av.available) {
+		ps3av_cmd_fin();
+		unregister_reboot_notifier(&ps3av_reboot_nb);
+	}
+	ps3av.available = 0;
+
+	return 0;
+}
+
+static struct ps3_vuart_port_driver ps3av_driver = {
+	.match_id = PS3_MATCH_ID_AV_SETTINGS,
+	.core = {
+		.name = "ps3_av",
+	},
+	.probe = ps3av_probe,
+	.remove = ps3av_remove,
+};
+
+static struct ps3_vuart_port_device ps3av_dev = {
+	.match_id = PS3_MATCH_ID_AV_SETTINGS
+};
+
+static int ps3av_module_init(void)
+{
+	int error = ps3_vuart_port_driver_register(&ps3av_driver);
+	if (error) {
+		printk(KERN_ERR
+		       "%s: ps3_vuart_port_driver_register failed %d\n",
+		       __FUNCTION__, error);
+		return error;
+	}
+
+	error = ps3_vuart_port_device_register(&ps3av_dev);
+	if (error)
+		printk(KERN_ERR
+		       "%s: ps3_vuart_port_device_register failed %d\n",
+		       __FUNCTION__, error);
+
+	return error;
+}
+
+static void __exit ps3av_module_exit(void)
+{
+	device_unregister(&ps3av_dev.core);
+	ps3_vuart_port_driver_unregister(&ps3av_driver);
+}
+
+subsys_initcall(ps3av_module_init);
+module_exit(ps3av_module_exit);
--- /dev/null
+++ ps3-linux/drivers/ps3/ps3av_cmd.c
@@ -0,0 +1,1052 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ * AV backend support for PS3
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/ps3av.h>
+#include <asm/ps3.h>
+
+#include "vuart.h"
+
+#ifdef PS3AV_DEBUG
+#define DPRINTK(fmt, args...) \
+	do { printk("ps3av " fmt, ## args); } while (0)
+#else
+#define DPRINTK(fmt, args...) do { } while (0)
+#endif
+
+static const struct video_fmt {
+	u32 format;
+	u32 order;
+} ps3av_video_fmt_table[] = {
+	{ PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_RGB },
+	{ PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_BGR },
+};
+
+static u32 ps3av_cs_video2av(int cs)
+{
+	u32 res = 0;
+
+	switch (cs) {
+	case PS3AV_CMD_VIDEO_CS_RGB_8:
+	case PS3AV_CMD_VIDEO_CS_RGB_10:
+	case PS3AV_CMD_VIDEO_CS_RGB_12:
+		res = PS3AV_CMD_AV_CS_RGB_8;
+		break;
+	case PS3AV_CMD_VIDEO_CS_YUV444_8:
+	case PS3AV_CMD_VIDEO_CS_YUV444_10:
+	case PS3AV_CMD_VIDEO_CS_YUV444_12:
+		res = PS3AV_CMD_AV_CS_YUV444_8;
+		break;
+	case PS3AV_CMD_VIDEO_CS_YUV422_8:
+	case PS3AV_CMD_VIDEO_CS_YUV422_10:
+	case PS3AV_CMD_VIDEO_CS_YUV422_12:
+		res = PS3AV_CMD_AV_CS_YUV422_8;
+		break;
+	case PS3AV_CMD_VIDEO_CS_XVYCC_8:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_10:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_12:
+		res = PS3AV_CMD_AV_CS_XVYCC_8;
+		break;
+	default:
+		res = PS3AV_CMD_AV_CS_RGB_8;
+		break;
+	}
+	return res;
+}
+
+static u32 ps3av_cs_video2av_bitlen(int cs)
+{
+	u32 res = 0;
+
+	switch (cs) {
+	case PS3AV_CMD_VIDEO_CS_RGB_8:
+	case PS3AV_CMD_VIDEO_CS_YUV444_8:
+	case PS3AV_CMD_VIDEO_CS_YUV422_8:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_8:
+		res = PS3AV_CMD_AV_CS_8;
+		break;
+	case PS3AV_CMD_VIDEO_CS_RGB_10:
+	case PS3AV_CMD_VIDEO_CS_YUV444_10:
+	case PS3AV_CMD_VIDEO_CS_YUV422_10:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_10:
+		res = PS3AV_CMD_AV_CS_10;
+		break;
+	case PS3AV_CMD_VIDEO_CS_RGB_12:
+	case PS3AV_CMD_VIDEO_CS_YUV444_12:
+	case PS3AV_CMD_VIDEO_CS_YUV422_12:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_12:
+		res = PS3AV_CMD_AV_CS_12;
+		break;
+	default:
+		res = PS3AV_CMD_AV_CS_8;
+		break;
+	}
+	return res;
+}
+
+static u32 ps3av_vid_video2av(int vid)
+{
+	u32 res = 0;
+
+	switch (vid) {
+	case PS3AV_CMD_VIDEO_VID_480I:
+		res = PS3AV_CMD_AV_VID_480I;
+		break;
+	case PS3AV_CMD_VIDEO_VID_480P:
+		res = PS3AV_CMD_AV_VID_480P;
+		break;
+	case PS3AV_CMD_VIDEO_VID_576I:
+		res = PS3AV_CMD_AV_VID_576I;
+		break;
+	case PS3AV_CMD_VIDEO_VID_576P:
+		res = PS3AV_CMD_AV_VID_576P;
+		break;
+	case PS3AV_CMD_VIDEO_VID_1080I_60HZ:
+		res = PS3AV_CMD_AV_VID_1080I_60HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_720P_60HZ:
+		res = PS3AV_CMD_AV_VID_720P_60HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_1080P_60HZ:
+		res = PS3AV_CMD_AV_VID_1080P_60HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_1080I_50HZ:
+		res = PS3AV_CMD_AV_VID_1080I_50HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_720P_50HZ:
+		res = PS3AV_CMD_AV_VID_720P_50HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_1080P_50HZ:
+		res = PS3AV_CMD_AV_VID_1080P_50HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_WXGA:
+		res = PS3AV_CMD_AV_VID_WXGA;
+		break;
+	case PS3AV_CMD_VIDEO_VID_SXGA:
+		res = PS3AV_CMD_AV_VID_SXGA;
+		break;
+	case PS3AV_CMD_VIDEO_VID_WUXGA:
+		res = PS3AV_CMD_AV_VID_WUXGA;
+		break;
+	default:
+		res = PS3AV_CMD_AV_VID_480P;
+		break;
+	}
+	return res;
+}
+
+int ps3av_cmd_init(void)
+{
+	int res;
+	struct ps3av_pkt_av_init av_init;
+	struct ps3av_pkt_video_init video_init;
+	struct ps3av_pkt_audio_init audio_init;
+
+	/* video init */
+	memset(&video_init, 0, sizeof(video_init));
+
+	res = ps3av_do_pkt(PS3AV_CID_VIDEO_INIT, sizeof(video_init.send_hdr),
+			   sizeof(video_init), &video_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&video_init);
+	if (res) {
+		printk(KERN_ERR "PS3AV_CID_VIDEO_INIT: failed %x\n", res);
+		return res;
+	}
+
+	/* audio init */
+	memset(&audio_init, 0, sizeof(audio_init));
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_INIT, sizeof(audio_init.send_hdr),
+			   sizeof(audio_init), &audio_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_init);
+	if (res) {
+		printk(KERN_ERR "PS3AV_CID_AUDIO_INIT: failed %x\n", res);
+		return res;
+	}
+
+	/* av init */
+	memset(&av_init, 0, sizeof(av_init));
+	av_init.event_bit = 0;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_INIT, sizeof(av_init), sizeof(av_init),
+			   &av_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_init);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_INIT: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_fin(void)
+{
+	int res;
+	struct ps3av_pkt_av_fin av_fin;
+
+	memset(&av_fin, 0, sizeof(av_fin));
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_FIN, sizeof(av_fin.send_hdr),
+			   sizeof(av_fin), &av_fin.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_fin);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_FIN: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_video_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, send_len, res;
+	struct ps3av_pkt_av_video_mute av_video_mute;
+
+	if (num_of_port > PS3AV_MUTE_PORT_MAX)
+		return -1;
+
+	memset(&av_video_mute, 0, sizeof(av_video_mute));
+	for (i = 0; i < num_of_port; i++) {
+		av_video_mute.mute[i].avport = port[i];
+		av_video_mute.mute[i].mute = mute;
+	}
+
+	send_len = sizeof(av_video_mute.send_hdr) +
+	    sizeof(struct ps3av_av_mute) * num_of_port;
+	res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_MUTE, send_len,
+			   sizeof(av_video_mute), &av_video_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_video_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_VIDEO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_video_disable_sig(u32 port)
+{
+	int res;
+	struct ps3av_pkt_av_video_disable_sig av_video_sig;
+
+	memset(&av_video_sig, 0, sizeof(av_video_sig));
+	av_video_sig.avport = port;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_DISABLE_SIG,
+			   sizeof(av_video_sig), sizeof(av_video_sig),
+			   &av_video_sig.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_video_sig);
+	if (res)
+		printk(KERN_ERR
+		       "PS3AV_CID_AV_VIDEO_DISABLE_SIG: failed %x port:%x\n",
+		       res, port);
+
+	return res;
+}
+
+int ps3av_cmd_av_tv_mute(u32 avport, u32 mute)
+{
+	int res;
+	struct ps3av_pkt_av_tv_mute tv_mute;
+
+	memset(&tv_mute, 0, sizeof(tv_mute));
+	tv_mute.avport = avport;
+	tv_mute.mute = mute;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_TV_MUTE, sizeof(tv_mute),
+			   sizeof(tv_mute), &tv_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&tv_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_TV_MUTE: failed %x port:%x\n",
+		       res, avport);
+
+	return res;
+}
+
+int ps3av_cmd_enable_event(void)
+{
+	int res;
+	struct ps3av_pkt_av_event av_event;
+
+	memset(&av_event, 0, sizeof(av_event));
+	av_event.event_bit = PS3AV_CMD_EVENT_BIT_UNPLUGGED |
+	    PS3AV_CMD_EVENT_BIT_PLUGGED | PS3AV_CMD_EVENT_BIT_HDCP_DONE;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_ENABLE_EVENT, sizeof(av_event),
+			   sizeof(av_event), &av_event.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_event);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_ENABLE_EVENT: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_hdmi_mode(u8 mode)
+{
+	int res;
+	struct ps3av_pkt_av_hdmi_mode hdmi_mode;
+
+	memset(&hdmi_mode, 0, sizeof(hdmi_mode));
+	hdmi_mode.mode = mode;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_HDMI_MODE, sizeof(hdmi_mode),
+			   sizeof(hdmi_mode), &hdmi_mode.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&hdmi_mode);
+	if (res && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+		printk(KERN_ERR "PS3AV_CID_AV_HDMI_MODE: failed %x\n", res);
+
+	return res;
+}
+
+u8 *ps3av_cmd_set_av_video_cs(u8 *p, u32 avport, int video_vid, int cs_out,
+			      int aspect, u32 id)
+{
+	struct ps3av_pkt_av_video_cs *av_video_cs;
+
+	av_video_cs = (struct ps3av_pkt_av_video_cs *)p;
+	if (video_vid == -1)
+		video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+	if (cs_out == -1)
+		cs_out = PS3AV_CMD_VIDEO_CS_YUV444_8;
+	if (aspect == -1)
+		aspect = 0;
+
+	memset(av_video_cs, 0, sizeof(*av_video_cs));
+	ps3av_set_hdr(PS3AV_CID_AV_VIDEO_CS, sizeof(*av_video_cs),
+		      &av_video_cs->send_hdr);
+	av_video_cs->avport = avport;
+	/* should be same as video_mode.resolution */
+	av_video_cs->av_vid = ps3av_vid_video2av(video_vid);
+	av_video_cs->av_cs_out = ps3av_cs_video2av(cs_out);
+	/* should be same as video_mode.video_cs_out */
+	av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
+	av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
+	av_video_cs->aspect = aspect;
+	if (id & PS3AV_MODE_DITHER) {
+		av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
+		    | PS3AV_CMD_AV_DITHER_8BIT;
+	} else {
+		/* default off */
+		av_video_cs->dither = PS3AV_CMD_AV_DITHER_OFF;
+	}
+
+	return p + sizeof(*av_video_cs);
+}
+
+u8 *ps3av_cmd_set_video_mode(u8 *p, u32 head, int video_vid, int video_fmt,
+			     u32 id)
+{
+	struct ps3av_pkt_video_mode *video_mode;
+	u32 x, y;
+
+	video_mode = (struct ps3av_pkt_video_mode *)p;
+	if (video_vid == -1)
+		video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+	if (video_fmt == -1)
+		video_fmt = PS3AV_CMD_VIDEO_FMT_X8R8G8B8;
+
+	if (ps3av_video_mode2res(id, &x, &y))
+		return p;
+
+	/* video mode */
+	memset(video_mode, 0, sizeof(*video_mode));
+	ps3av_set_hdr(PS3AV_CID_VIDEO_MODE, sizeof(*video_mode),
+		      &video_mode->send_hdr);
+	video_mode->video_head = head;
+	if (video_vid == PS3AV_CMD_VIDEO_VID_480I
+	    && head == PS3AV_CMD_VIDEO_HEAD_B)
+		video_mode->video_vid = PS3AV_CMD_VIDEO_VID_480I_A;
+	else
+		video_mode->video_vid = video_vid;
+	video_mode->width = (u16) x;
+	video_mode->height = (u16) y;
+	video_mode->pitch = video_mode->width * 4;	/* line_length */
+	video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
+	video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
+	video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
+
+	DPRINTK("video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
+		video_vid, video_mode->width, video_mode->height,
+		video_mode->pitch, video_mode->video_out_format,
+		video_mode->video_format, video_mode->video_order);
+	return p + sizeof(*video_mode);
+}
+
+int ps3av_cmd_video_format_black(u32 head, u32 video_fmt, u32 mute)
+{
+	int res;
+	struct ps3av_pkt_video_format video_format;
+
+	memset(&video_format, 0, sizeof(video_format));
+	video_format.video_head = head;
+	if (mute != PS3AV_CMD_MUTE_OFF)
+		video_format.video_format = PS3AV_CMD_VIDEO_FORMAT_BLACK;
+	else
+		video_format.video_format =
+		    ps3av_video_fmt_table[video_fmt].format;
+	video_format.video_order = ps3av_video_fmt_table[video_fmt].order;
+
+	res = ps3av_do_pkt(PS3AV_CID_VIDEO_FORMAT, sizeof(video_format),
+			   sizeof(video_format), &video_format.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&video_format);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_VIDEO_FORMAT: failed %x\n", res);
+
+	return res;
+}
+
+
+int ps3av_cmd_av_audio_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, res;
+	struct ps3av_pkt_av_audio_mute av_audio_mute;
+
+	if (num_of_port > PS3AV_MUTE_PORT_MAX)
+		return -1;
+
+	/* audio mute */
+	memset(&av_audio_mute, 0, sizeof(av_audio_mute));
+	for (i = 0; i < num_of_port; i++) {
+		av_audio_mute.mute[i].avport = port[i];
+		av_audio_mute.mute[i].mute = mute;
+	}
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_AUDIO_MUTE,
+			   sizeof(av_audio_mute.send_hdr) +
+			   sizeof(struct ps3av_av_mute) * num_of_port,
+			   sizeof(av_audio_mute), &av_audio_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_audio_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+static u8 ps3av_cnv_mclk(u32 fs)
+{
+	u8 mclk;
+
+	switch (fs) {
+	case PS3AV_CMD_AUDIO_FS_44K:
+		mclk = PS3AV_CMD_AV_MCLK_512;
+		break;
+	case PS3AV_CMD_AUDIO_FS_48K:
+		mclk = PS3AV_CMD_AV_MCLK_512;
+		break;
+	case PS3AV_CMD_AUDIO_FS_88K:
+		mclk = PS3AV_CMD_AV_MCLK_256;
+		break;
+	case PS3AV_CMD_AUDIO_FS_96K:
+		mclk = PS3AV_CMD_AV_MCLK_256;
+		break;
+	case PS3AV_CMD_AUDIO_FS_176K:
+		mclk = PS3AV_CMD_AV_MCLK_128;
+		break;
+	case PS3AV_CMD_AUDIO_FS_192K:
+		mclk = PS3AV_CMD_AV_MCLK_128;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+		mclk = 0;
+		break;
+	}
+	return mclk;
+}
+
+static const u32 ps3av_ns_table[][5] = {
+	/*   D1,    D2,    D3,    D4,    D5 */
+	{  6272,  6272, 17836, 17836,  8918 },	/*  44K */
+	{  6144,  6144, 11648, 11648,  5824 },	/*  48K */
+	{ 12544, 12544, 35672, 35672, 17836 },	/*  88K */
+	{ 12288, 12288, 23296, 23296, 11648 },	/*  96K */
+	{ 25088, 25088, 71344, 71344, 35672 },	/* 176K */
+	{ 24576, 24576, 46592, 46592, 23296 },	/* 192K */
+};
+
+static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
+{
+	u32 av_vid, ns_val;
+	u8 *p = ns;
+	int d;
+
+	d = ns_val = 0;
+	av_vid = ps3av_vid_video2av(video_vid);
+	switch (av_vid) {
+	case PS3AV_CMD_AV_VID_480I:
+	case PS3AV_CMD_AV_VID_576I:
+		d = 0;
+		break;
+	case PS3AV_CMD_AV_VID_480P:
+	case PS3AV_CMD_AV_VID_576P:
+		d = 1;
+		break;
+	case PS3AV_CMD_AV_VID_1080I_60HZ:
+	case PS3AV_CMD_AV_VID_1080I_50HZ:
+		d = 2;
+		break;
+	case PS3AV_CMD_AV_VID_720P_60HZ:
+	case PS3AV_CMD_AV_VID_720P_50HZ:
+		d = 3;
+		break;
+	case PS3AV_CMD_AV_VID_1080P_60HZ:
+	case PS3AV_CMD_AV_VID_1080P_50HZ:
+	case PS3AV_CMD_AV_VID_WXGA:
+	case PS3AV_CMD_AV_VID_SXGA:
+	case PS3AV_CMD_AV_VID_WUXGA:
+		d = 4;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, vid:%x\n", __FUNCTION__,
+		       video_vid);
+		break;
+	}
+
+	switch (fs) {
+	case PS3AV_CMD_AUDIO_FS_44K:
+		ns_val = ps3av_ns_table[0][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_48K:
+		ns_val = ps3av_ns_table[1][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_88K:
+		ns_val = ps3av_ns_table[2][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_96K:
+		ns_val = ps3av_ns_table[3][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_176K:
+		ns_val = ps3av_ns_table[4][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_192K:
+		ns_val = ps3av_ns_table[5][d];
+		break;
+	default:
+		printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+		break;
+	}
+	*p++ = ns_val & 0x000000FF;
+	*p++ = (ns_val & 0x0000FF00) >> 8;
+	*p = (ns_val & 0x00FF0000) >> 16;
+}
+
+static u8 ps3av_cnv_enable(u32 source, u8 *enable)
+{
+	u8 *p, ret = 0;
+
+	if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) {
+		ret = 0x03;
+	} else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) {
+		p = enable;
+		ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) |
+		      0x01;
+	} else
+		printk(KERN_ERR "%s failed, source:%x\n", __FUNCTION__,
+		       source);
+	return ret;
+}
+
+static u8 ps3av_cnv_fifomap(u8 *map)
+{
+	u8 *p, ret = 0;
+
+	p = map;
+	ret = p[0] + (p[1] << 2) + (p[2] << 4) + (p[3] << 6);
+	return ret;
+}
+
+static u8 ps3av_cnv_inputlen(u32 word_bits)
+{
+	u8 ret = 0;
+
+	switch (word_bits) {
+	case PS3AV_CMD_AUDIO_WORD_BITS_16:
+		ret = PS3AV_CMD_AV_INPUTLEN_16;
+		break;
+	case PS3AV_CMD_AUDIO_WORD_BITS_20:
+		ret = PS3AV_CMD_AV_INPUTLEN_20;
+		break;
+	case PS3AV_CMD_AUDIO_WORD_BITS_24:
+		ret = PS3AV_CMD_AV_INPUTLEN_24;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, word_bits:%x\n", __FUNCTION__,
+		       word_bits);
+		break;
+	}
+	return ret;
+}
+
+static u8 ps3av_cnv_layout(u32 num_of_ch)
+{
+	if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) {
+		printk(KERN_ERR "%s failed, num_of_ch:%x\n", __FUNCTION__,
+		       num_of_ch);
+		return 0;
+	}
+
+	return num_of_ch == PS3AV_CMD_AUDIO_NUM_OF_CH_2 ? 0x0 : 0x1;
+}
+
+static void ps3av_cnv_info(struct ps3av_audio_info_frame *info,
+			   const struct ps3av_pkt_audio_mode *mode)
+{
+	info->pb1.cc = mode->audio_num_of_ch + 1;	/* CH2:0x01 --- CH8:0x07 */
+	info->pb1.ct = 0;
+	info->pb2.sf = 0;
+	info->pb2.ss = 0;
+
+	info->pb3 = 0;		/* check mode->audio_format ?? */
+	info->pb4 = mode->audio_layout;
+	info->pb5.dm = mode->audio_downmix;
+	info->pb5.lsv = mode->audio_downmix_level;
+}
+
+static void ps3av_cnv_chstat(u8 *chstat, u8 *cs_info)
+{
+	memcpy(chstat, cs_info, 5);
+}
+
+u8 *ps3av_cmd_set_av_audio_param(u8 *p, u32 port,
+				 const struct ps3av_pkt_audio_mode *audio_mode,
+				 u32 video_vid)
+{
+	struct ps3av_pkt_av_audio_param *param;
+
+	param = (struct ps3av_pkt_av_audio_param *)p;
+
+	memset(param, 0, sizeof(*param));
+	ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM, sizeof(*param),
+		      &param->send_hdr);
+
+	param->avport = port;
+	param->mclk = ps3av_cnv_mclk(audio_mode->audio_fs) | 0x80;
+	ps3av_cnv_ns(param->ns, audio_mode->audio_fs, video_vid);
+	param->enable = ps3av_cnv_enable(audio_mode->audio_source,
+					 audio_mode->audio_enable);
+	param->swaplr = 0x09;
+	param->fifomap = ps3av_cnv_fifomap(audio_mode->audio_map);
+	param->inputctrl = 0x49;
+	param->inputlen = ps3av_cnv_inputlen(audio_mode->audio_word_bits);
+	param->layout = ps3av_cnv_layout(audio_mode->audio_num_of_ch);
+	ps3av_cnv_info(&param->info, audio_mode);
+	ps3av_cnv_chstat(param->chstat, audio_mode->audio_cs_info);
+
+	return p + sizeof(*param);
+}
+
+/* default cs val */
+static const u8 ps3av_mode_cs_info[] = {
+	0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
+};
+
+#define CS_44	0x00
+#define CS_48	0x02
+#define CS_88	0x08
+#define CS_96	0x0a
+#define CS_176	0x0c
+#define CS_192	0x0e
+#define CS_MASK	0x0f
+#define CS_BIT	0x40
+
+void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
+			      u32 ch, u32 fs, u32 word_bits, u32 format,
+			      u32 source)
+{
+	int spdif_through, spdif_bitstream;
+	int i;
+
+	if (!(ch | fs | format | word_bits | source)) {
+		ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2;
+		fs = PS3AV_CMD_AUDIO_FS_48K;
+		word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
+		format = PS3AV_CMD_AUDIO_FORMAT_PCM;
+		source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
+	}
+	spdif_through = spdif_bitstream = 0;	/* XXX not supported */
+
+	/* audio mode */
+	memset(audio, 0, sizeof(*audio));
+	ps3av_set_hdr(PS3AV_CID_AUDIO_MODE, sizeof(*audio), &audio->send_hdr);
+
+	audio->avport = (u8) avport;
+	audio->mask = 0x0FFF;	/* XXX set all */
+	audio->audio_num_of_ch = ch;
+	audio->audio_fs = fs;
+	audio->audio_word_bits = word_bits;
+	audio->audio_format = format;
+	audio->audio_source = source;
+
+	switch (ch) {
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
+		audio->audio_enable[3] = 1;
+		/* fall through */
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
+		audio->audio_enable[2] = 1;
+		audio->audio_enable[1] = 1;
+		/* fall through */
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
+	default:
+		audio->audio_enable[0] = 1;
+	}
+
+	/* audio swap L/R */
+	for (i = 0; i < 4; i++)
+		audio->audio_swap[i] = PS3AV_CMD_AUDIO_SWAP_0;	/* no swap */
+
+	/* audio serial input mapping */
+	audio->audio_map[0] = PS3AV_CMD_AUDIO_MAP_OUTPUT_0;
+	audio->audio_map[1] = PS3AV_CMD_AUDIO_MAP_OUTPUT_1;
+	audio->audio_map[2] = PS3AV_CMD_AUDIO_MAP_OUTPUT_2;
+	audio->audio_map[3] = PS3AV_CMD_AUDIO_MAP_OUTPUT_3;
+
+	/* audio speaker layout */
+	if (avport == PS3AV_CMD_AVPORT_HDMI_0 ||
+	    avport == PS3AV_CMD_AVPORT_HDMI_1) {
+		switch (ch) {
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_8CH;
+			break;
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_6CH;
+			break;
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
+		default:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
+			break;
+		}
+	} else {
+		audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
+	}
+
+	/* audio downmix permission */
+	audio->audio_downmix = PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED;
+	/* audio downmix level shift (0:0dB to 15:15dB) */
+	audio->audio_downmix_level = 0;	/* 0dB */
+
+	/* set ch status */
+	for (i = 0; i < 8; i++)
+		audio->audio_cs_info[i] = ps3av_mode_cs_info[i];
+
+	switch (fs) {
+	case PS3AV_CMD_AUDIO_FS_44K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_44;
+		break;
+	case PS3AV_CMD_AUDIO_FS_88K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_88;
+		break;
+	case PS3AV_CMD_AUDIO_FS_96K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_96;
+		break;
+	case PS3AV_CMD_AUDIO_FS_176K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_176;
+		break;
+	case PS3AV_CMD_AUDIO_FS_192K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_192;
+		break;
+	default:
+		break;
+	}
+
+	/* pass through setting */
+	if (spdif_through &&
+	    (avport == PS3AV_CMD_AVPORT_SPDIF_0 ||
+	     avport == PS3AV_CMD_AVPORT_SPDIF_1)) {
+		audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
+		audio->audio_source = PS3AV_CMD_AUDIO_SOURCE_SPDIF;
+		if (spdif_bitstream) {
+			audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
+			audio->audio_cs_info[0] |= CS_BIT;
+		}
+	}
+}
+
+int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *audio_mode)
+{
+	int res;
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MODE, sizeof(*audio_mode),
+			   sizeof(*audio_mode), &audio_mode->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(audio_mode);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_MODE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_audio_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, res;
+	struct ps3av_pkt_audio_mute audio_mute;
+
+	if (num_of_port > PS3AV_OPT_PORT_MAX)
+		return -1;
+
+	/* audio mute */
+	memset(&audio_mute, 0, sizeof(audio_mute));
+	for (i = 0; i < num_of_port; i++) {
+		audio_mute.mute[i].avport = port[i];
+		audio_mute.mute[i].mute = mute;
+	}
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MUTE,
+			   sizeof(audio_mute.send_hdr) +
+			   sizeof(struct ps3av_audio_mute) * num_of_port,
+			   sizeof(audio_mute), &audio_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_audio_active(int active, u32 port)
+{
+	int res;
+	struct ps3av_pkt_audio_active audio_active;
+	u32 cid;
+
+	/* audio active */
+	memset(&audio_active, 0, sizeof(audio_active));
+	audio_active.audio_port = port;
+	cid = active ? PS3AV_CID_AUDIO_ACTIVE : PS3AV_CID_AUDIO_INACTIVE;
+
+	res = ps3av_do_pkt(cid, sizeof(audio_active), sizeof(audio_active),
+			   &audio_active.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_active);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid,
+		       res);
+
+	return res;
+}
+
+int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
+{
+	int res;
+
+	/* avb packet */
+
+	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
+			   &avb->send_hdr);
+	if (res < 0)
+		goto out;
+
+	res = get_status(avb);
+	if (res)
+		DPRINTK("PS3AV_CID_AVB_PARAM: failed %x\n", res);
+
+      out:
+	return res;
+}
+
+int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *hw_conf)
+{
+	int res;
+
+	memset(hw_conf, 0, sizeof(*hw_conf));
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF, sizeof(hw_conf->send_hdr),
+			   sizeof(*hw_conf), &hw_conf->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(hw_conf);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info,
+				     u32 avport)
+{
+	int res;
+
+	memset(info, 0, sizeof(*info));
+	info->avport = avport;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_GET_MONITOR_INFO,
+			   sizeof(info->send_hdr) + sizeof(info->avport) +
+			   sizeof(info->reserved),
+			   sizeof(*info), &info->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(info);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n",
+		       res);
+
+	return res;
+}
+
+#ifdef PS3AV_DEBUG
+int ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf)
+{
+	printk("av_h_conf:num of hdmi:%d\n", hw_conf->num_of_hdmi);
+	printk("av_h_conf:num of avmulti:%d\n", hw_conf->num_of_avmulti);
+	printk("av_h_conf:num of spdif:%d\n", hw_conf->num_of_spdif);
+	return 0;
+}
+
+int ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info)
+{
+	const struct ps3av_info_monitor *info = &monitor_info->info;
+	const struct ps3av_info_audio *audio = info->audio;
+	int i;
+
+	printk("Monitor Info: size%d\n", monitor_info->send_hdr.size);
+
+	printk("avport:%02x\n", info->avport);
+	printk("monitor_id:");
+	for (i = 0; i < 10; i++)
+		printk("%02x ", info->monitor_id[i]);
+	printk("\nmonitor_type:%02x\n", info->monitor_type);
+	printk("monitor_name:");
+	for (i = 0; i < 16; i++)
+		printk("%c", info->monitor_name[i]);
+
+	/* resolution */
+	printk("\nresolution_60: bits:%08x native:%08x\n",
+	       info->res_60.res_bits, info->res_60.native);
+	printk("resolution_50: bits:%08x native:%08x\n",
+	       info->res_50.res_bits, info->res_50.native);
+	printk("resolution_other: bits:%08x native:%08x\n",
+	       info->res_other.res_bits, info->res_other.native);
+	printk("resolution_vesa: bits:%08x native:%08x\n",
+	       info->res_vesa.res_bits, info->res_vesa.native);
+
+	/* color space */
+	printk("color space    rgb:%02x\n", info->cs.rgb);
+	printk("color space yuv444:%02x\n", info->cs.yuv444);
+	printk("color space yuv422:%02x\n", info->cs.yuv422);
+
+	/* color info */
+	printk("color info   red:X %04x Y %04x\n",
+	       info->color.red_x, info->color.red_y);
+	printk("color info green:X %04x Y %04x\n",
+	       info->color.green_x, info->color.green_y);
+	printk("color info  blue:X %04x Y %04x\n",
+	       info->color.blue_x, info->color.blue_y);
+	printk("color info white:X %04x Y %04x\n",
+	       info->color.white_x, info->color.white_y);
+	printk("color info gamma: %08x\n", info->color.gamma);
+
+	/* other info */
+	printk("supported_AI:%02x\n", info->supported_ai);
+	printk("speaker_info:%02x\n", info->speaker_info);
+	printk("num of audio:%02x\n", info->num_of_audio_block);
+
+	/* audio block */
+	for (i = 0; i < info->num_of_audio_block; i++) {
+		printk("audio[%d] type:%02x max_ch:%02x fs:%02x sbit:%02x\n",
+		       i, audio->type, audio->max_num_of_ch, audio->fs,
+		       audio->sbit);
+		audio++;
+	}
+
+	return 0;
+}
+#endif /* PS3AV_DEBUG */
+
+#define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \
+		| PS3AV_CMD_AV_LAYOUT_44 \
+		| PS3AV_CMD_AV_LAYOUT_48)
+
+#define PS3AV_AV_LAYOUT_1 (PS3AV_AV_LAYOUT_0 \
+		| PS3AV_CMD_AV_LAYOUT_88 \
+		| PS3AV_CMD_AV_LAYOUT_96 \
+		| PS3AV_CMD_AV_LAYOUT_176 \
+		| PS3AV_CMD_AV_LAYOUT_192)
+
+/************************* vuart ***************************/
+
+#define POLLING_INTERVAL  25	/* in msec */
+
+int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
+		      unsigned long size)
+{
+	int error = ps3_vuart_write(dev, buf, size);
+	return error ? error : size;
+}
+
+int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
+		     unsigned long size, int timeout)
+{
+	int error;
+	int loopcnt = 0;
+
+	timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
+	while (loopcnt++ <= timeout) {
+		error = ps3_vuart_read(dev, buf, size);
+		if (!error)
+			return size;
+		if (error != -EAGAIN) {
+			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
+			       __FUNCTION__, error);
+			return error;
+		}
+		msleep(POLLING_INTERVAL);
+	}
+	return -EWOULDBLOCK;
+}
--- /dev/null
+++ ps3-linux/include/asm-powerpc/ps3av.h
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef _PS3AV_H_
+#define _PS3AV_H_
+
+/** command for ioctl() **/
+#define PS3AV_VERSION 0x205	/* version of ps3av command */
+
+#define PS3AV_CID_AV_INIT              0x00000001
+#define PS3AV_CID_AV_FIN               0x00000002
+#define PS3AV_CID_AV_GET_HW_CONF       0x00000003
+#define PS3AV_CID_AV_GET_MONITOR_INFO  0x00000004
+#define PS3AV_CID_AV_ENABLE_EVENT      0x00000006
+#define PS3AV_CID_AV_DISABLE_EVENT     0x00000007
+#define PS3AV_CID_AV_TV_MUTE           0x0000000a
+
+#define PS3AV_CID_AV_VIDEO_CS          0x00010001
+#define PS3AV_CID_AV_VIDEO_MUTE        0x00010002
+#define PS3AV_CID_AV_VIDEO_DISABLE_SIG 0x00010003
+#define PS3AV_CID_AV_AUDIO_PARAM       0x00020001
+#define PS3AV_CID_AV_AUDIO_MUTE        0x00020002
+#define PS3AV_CID_AV_HDMI_MODE         0x00040001
+
+#define PS3AV_CID_VIDEO_INIT           0x01000001
+#define PS3AV_CID_VIDEO_MODE           0x01000002
+#define PS3AV_CID_VIDEO_FORMAT         0x01000004
+#define PS3AV_CID_VIDEO_PITCH          0x01000005
+
+#define PS3AV_CID_AUDIO_INIT           0x02000001
+#define PS3AV_CID_AUDIO_MODE           0x02000002
+#define PS3AV_CID_AUDIO_MUTE           0x02000003
+#define PS3AV_CID_AUDIO_ACTIVE         0x02000004
+#define PS3AV_CID_AUDIO_INACTIVE       0x02000005
+#define PS3AV_CID_AUDIO_SPDIF_BIT      0x02000006
+#define PS3AV_CID_AUDIO_CTRL           0x02000007
+
+#define PS3AV_CID_EVENT_UNPLUGGED      0x10000001
+#define PS3AV_CID_EVENT_PLUGGED        0x10000002
+#define PS3AV_CID_EVENT_HDCP_DONE      0x10000003
+#define PS3AV_CID_EVENT_HDCP_FAIL      0x10000004
+#define PS3AV_CID_EVENT_HDCP_AUTH      0x10000005
+#define PS3AV_CID_EVENT_HDCP_ERROR     0x10000006
+
+#define PS3AV_CID_AVB_PARAM            0x04000001
+
+/* max backend ports */
+#define PS3AV_HDMI_MAX                 2	/* HDMI_0 HDMI_1 */
+#define PS3AV_AVMULTI_MAX              1	/* AVMULTI_0 */
+#define PS3AV_AV_PORT_MAX              (PS3AV_HDMI_MAX + PS3AV_AVMULTI_MAX)
+#define PS3AV_OPT_PORT_MAX             1	/* SPDIF0 */
+#define PS3AV_HEAD_MAX                 2	/* HEAD_A HEAD_B */
+
+/* num of pkt for PS3AV_CID_AVB_PARAM */
+#define PS3AV_AVB_NUM_VIDEO            PS3AV_HEAD_MAX
+#define PS3AV_AVB_NUM_AUDIO            0	/* not supported */
+#define PS3AV_AVB_NUM_AV_VIDEO         PS3AV_AV_PORT_MAX
+#define PS3AV_AVB_NUM_AV_AUDIO         PS3AV_HDMI_MAX
+
+#define PS3AV_MUTE_PORT_MAX            1	/* num of ports in mute pkt */
+
+/* event_bit */
+#define PS3AV_CMD_EVENT_BIT_UNPLUGGED			(1 << 0)
+#define PS3AV_CMD_EVENT_BIT_PLUGGED			(1 << 1)
+#define PS3AV_CMD_EVENT_BIT_HDCP_DONE			(1 << 2)
+#define PS3AV_CMD_EVENT_BIT_HDCP_FAIL			(1 << 3)
+#define PS3AV_CMD_EVENT_BIT_HDCP_REAUTH			(1 << 4)
+#define PS3AV_CMD_EVENT_BIT_HDCP_TOPOLOGY		(1 << 5)
+
+/* common params */
+/* mute */
+#define PS3AV_CMD_MUTE_OFF				0x0000
+#define PS3AV_CMD_MUTE_ON				0x0001
+/* avport */
+#define PS3AV_CMD_AVPORT_HDMI_0				0x0000
+#define PS3AV_CMD_AVPORT_HDMI_1				0x0001
+#define PS3AV_CMD_AVPORT_AVMULTI_0			0x0010
+#define PS3AV_CMD_AVPORT_SPDIF_0			0x0020
+#define PS3AV_CMD_AVPORT_SPDIF_1			0x0021
+
+/* for av backend */
+/* av_mclk */
+#define PS3AV_CMD_AV_MCLK_128				0x0000
+#define PS3AV_CMD_AV_MCLK_256				0x0001
+#define PS3AV_CMD_AV_MCLK_512				0x0003
+/* av_inputlen */
+#define PS3AV_CMD_AV_INPUTLEN_16			0x02
+#define PS3AV_CMD_AV_INPUTLEN_20			0x0a
+#define PS3AV_CMD_AV_INPUTLEN_24			0x0b
+/* alayout */
+#define PS3AV_CMD_AV_LAYOUT_32				(1 << 0)
+#define PS3AV_CMD_AV_LAYOUT_44				(1 << 1)
+#define PS3AV_CMD_AV_LAYOUT_48				(1 << 2)
+#define PS3AV_CMD_AV_LAYOUT_88				(1 << 3)
+#define PS3AV_CMD_AV_LAYOUT_96				(1 << 4)
+#define PS3AV_CMD_AV_LAYOUT_176				(1 << 5)
+#define PS3AV_CMD_AV_LAYOUT_192				(1 << 6)
+/* hdmi_mode */
+#define PS3AV_CMD_AV_HDMI_MODE_NORMAL			0xff
+#define PS3AV_CMD_AV_HDMI_HDCP_OFF			0x01
+#define PS3AV_CMD_AV_HDMI_EDID_PASS			0x80
+#define PS3AV_CMD_AV_HDMI_DVI				0x40
+
+/* for video module */
+/* video_head */
+#define PS3AV_CMD_VIDEO_HEAD_A				0x0000
+#define PS3AV_CMD_VIDEO_HEAD_B				0x0001
+/* video_cs_out video_cs_in */
+#define PS3AV_CMD_VIDEO_CS_NONE				0x0000
+#define PS3AV_CMD_VIDEO_CS_RGB_8			0x0001
+#define PS3AV_CMD_VIDEO_CS_YUV444_8			0x0002
+#define PS3AV_CMD_VIDEO_CS_YUV422_8			0x0003
+#define PS3AV_CMD_VIDEO_CS_XVYCC_8			0x0004
+#define PS3AV_CMD_VIDEO_CS_RGB_10			0x0005
+#define PS3AV_CMD_VIDEO_CS_YUV444_10			0x0006
+#define PS3AV_CMD_VIDEO_CS_YUV422_10			0x0007
+#define PS3AV_CMD_VIDEO_CS_XVYCC_10			0x0008
+#define PS3AV_CMD_VIDEO_CS_RGB_12			0x0009
+#define PS3AV_CMD_VIDEO_CS_YUV444_12			0x000a
+#define PS3AV_CMD_VIDEO_CS_YUV422_12			0x000b
+#define PS3AV_CMD_VIDEO_CS_XVYCC_12			0x000c
+/* video_vid */
+#define PS3AV_CMD_VIDEO_VID_NONE			0x0000
+#define PS3AV_CMD_VIDEO_VID_480I			0x0001
+#define PS3AV_CMD_VIDEO_VID_576I			0x0003
+#define PS3AV_CMD_VIDEO_VID_480P			0x0005
+#define PS3AV_CMD_VIDEO_VID_576P			0x0006
+#define PS3AV_CMD_VIDEO_VID_1080I_60HZ			0x0007
+#define PS3AV_CMD_VIDEO_VID_1080I_50HZ			0x0008
+#define PS3AV_CMD_VIDEO_VID_720P_60HZ			0x0009
+#define PS3AV_CMD_VIDEO_VID_720P_50HZ			0x000a
+#define PS3AV_CMD_VIDEO_VID_1080P_60HZ			0x000b
+#define PS3AV_CMD_VIDEO_VID_1080P_50HZ			0x000c
+#define PS3AV_CMD_VIDEO_VID_WXGA			0x000d
+#define PS3AV_CMD_VIDEO_VID_SXGA			0x000e
+#define PS3AV_CMD_VIDEO_VID_WUXGA			0x000f
+#define PS3AV_CMD_VIDEO_VID_480I_A			0x0010
+/* video_format */
+#define PS3AV_CMD_VIDEO_FORMAT_BLACK			0x0000
+#define PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT		0x0007
+/* video_order */
+#define PS3AV_CMD_VIDEO_ORDER_RGB			0x0000
+#define PS3AV_CMD_VIDEO_ORDER_BGR			0x0001
+/* video_fmt */
+#define PS3AV_CMD_VIDEO_FMT_X8R8G8B8			0x0000
+/* video_out_format */
+#define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT		0x0000
+/* video_sync */
+#define PS3AV_CMD_VIDEO_SYNC_VSYNC			0x0001
+#define PS3AV_CMD_VIDEO_SYNC_CSYNC			0x0004
+#define PS3AV_CMD_VIDEO_SYNC_HSYNC			0x0010
+
+/* for audio module */
+/* num_of_ch */
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_2			0x0000
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_3			0x0001
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_4			0x0002
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_5			0x0003
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_6			0x0004
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_7			0x0005
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_8			0x0006
+/* audio_fs */
+#define PS3AV_CMD_AUDIO_FS_32K				0x0001
+#define PS3AV_CMD_AUDIO_FS_44K				0x0002
+#define PS3AV_CMD_AUDIO_FS_48K				0x0003
+#define PS3AV_CMD_AUDIO_FS_88K				0x0004
+#define PS3AV_CMD_AUDIO_FS_96K				0x0005
+#define PS3AV_CMD_AUDIO_FS_176K				0x0006
+#define PS3AV_CMD_AUDIO_FS_192K				0x0007
+/* audio_word_bits */
+#define PS3AV_CMD_AUDIO_WORD_BITS_16			0x0001
+#define PS3AV_CMD_AUDIO_WORD_BITS_20			0x0002
+#define PS3AV_CMD_AUDIO_WORD_BITS_24			0x0003
+/* audio_format */
+#define PS3AV_CMD_AUDIO_FORMAT_PCM			0x0001
+#define PS3AV_CMD_AUDIO_FORMAT_BITSTREAM		0x00ff
+/* audio_source */
+#define PS3AV_CMD_AUDIO_SOURCE_SERIAL			0x0000
+#define PS3AV_CMD_AUDIO_SOURCE_SPDIF			0x0001
+/* audio_swap */
+#define PS3AV_CMD_AUDIO_SWAP_0				0x0000
+#define PS3AV_CMD_AUDIO_SWAP_1				0x0000
+/* audio_map */
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_0			0x0000
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_1			0x0001
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_2			0x0002
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_3			0x0003
+/* audio_layout */
+#define PS3AV_CMD_AUDIO_LAYOUT_2CH			0x0000
+#define PS3AV_CMD_AUDIO_LAYOUT_6CH			0x000b	/* LREClr */
+#define PS3AV_CMD_AUDIO_LAYOUT_8CH			0x001f	/* LREClrXY */
+/* audio_downmix */
+#define PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED		0x0000
+#define PS3AV_CMD_AUDIO_DOWNMIX_PROHIBITED		0x0001
+
+/* audio_port */
+#define PS3AV_CMD_AUDIO_PORT_HDMI_0			( 1 << 0 )
+#define PS3AV_CMD_AUDIO_PORT_HDMI_1			( 1 << 1 )
+#define PS3AV_CMD_AUDIO_PORT_AVMULTI_0			( 1 << 10 )
+#define PS3AV_CMD_AUDIO_PORT_SPDIF_0			( 1 << 20 )
+#define PS3AV_CMD_AUDIO_PORT_SPDIF_1			( 1 << 21 )
+
+/* audio_ctrl_id */
+#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_RESET		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_DE_EMPHASIS		0x0001
+#define PS3AV_CMD_AUDIO_CTRL_ID_AVCLK			0x0002
+/* audio_ctrl_data[0] reset */
+#define PS3AV_CMD_AUDIO_CTRL_RESET_NEGATE		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_RESET_ASSERT		0x0001
+/* audio_ctrl_data[0] de-emphasis */
+#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_OFF		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_ON		0x0001
+/* audio_ctrl_data[0] avclk */
+#define PS3AV_CMD_AUDIO_CTRL_AVCLK_22			0x0000
+#define PS3AV_CMD_AUDIO_CTRL_AVCLK_18			0x0001
+
+/* av_vid */
+/* do not use these params directly, use vid_video2av */
+#define PS3AV_CMD_AV_VID_480I				0x0000
+#define PS3AV_CMD_AV_VID_480P				0x0001
+#define PS3AV_CMD_AV_VID_720P_60HZ			0x0002
+#define PS3AV_CMD_AV_VID_1080I_60HZ			0x0003
+#define PS3AV_CMD_AV_VID_1080P_60HZ			0x0004
+#define PS3AV_CMD_AV_VID_576I				0x0005
+#define PS3AV_CMD_AV_VID_576P				0x0006
+#define PS3AV_CMD_AV_VID_720P_50HZ			0x0007
+#define PS3AV_CMD_AV_VID_1080I_50HZ			0x0008
+#define PS3AV_CMD_AV_VID_1080P_50HZ			0x0009
+#define PS3AV_CMD_AV_VID_WXGA				0x000a
+#define PS3AV_CMD_AV_VID_SXGA				0x000b
+#define PS3AV_CMD_AV_VID_WUXGA				0x000c
+/* av_cs_out av_cs_in */
+/* use cs_video2av() */
+#define PS3AV_CMD_AV_CS_RGB_8				0x0000
+#define PS3AV_CMD_AV_CS_YUV444_8			0x0001
+#define PS3AV_CMD_AV_CS_YUV422_8			0x0002
+#define PS3AV_CMD_AV_CS_XVYCC_8				0x0003
+#define PS3AV_CMD_AV_CS_RGB_10				0x0004
+#define PS3AV_CMD_AV_CS_YUV444_10			0x0005
+#define PS3AV_CMD_AV_CS_YUV422_10			0x0006
+#define PS3AV_CMD_AV_CS_XVYCC_10			0x0007
+#define PS3AV_CMD_AV_CS_RGB_12				0x0008
+#define PS3AV_CMD_AV_CS_YUV444_12			0x0009
+#define PS3AV_CMD_AV_CS_YUV422_12			0x000a
+#define PS3AV_CMD_AV_CS_XVYCC_12			0x000b
+#define PS3AV_CMD_AV_CS_8				0x0000
+#define PS3AV_CMD_AV_CS_10				0x0001
+#define PS3AV_CMD_AV_CS_12				0x0002
+/* dither */
+#define PS3AV_CMD_AV_DITHER_OFF				0x0000
+#define PS3AV_CMD_AV_DITHER_ON				0x0001
+#define PS3AV_CMD_AV_DITHER_8BIT			0x0000
+#define PS3AV_CMD_AV_DITHER_10BIT			0x0002
+#define PS3AV_CMD_AV_DITHER_12BIT			0x0004
+/* super_white */
+#define PS3AV_CMD_AV_SUPER_WHITE_OFF			0x0000
+#define PS3AV_CMD_AV_SUPER_WHITE_ON			0x0001
+/* aspect */
+#define PS3AV_CMD_AV_ASPECT_16_9			0x0000
+#define PS3AV_CMD_AV_ASPECT_4_3				0x0001
+/* video_cs_cnv() */
+#define PS3AV_CMD_VIDEO_CS_RGB				0x0001
+#define PS3AV_CMD_VIDEO_CS_YUV422			0x0002
+#define PS3AV_CMD_VIDEO_CS_YUV444			0x0003
+
+/* for automode */
+#define PS3AV_RESBIT_720x480P			0x0003	/* 0x0001 | 0x0002 */
+#define PS3AV_RESBIT_720x576P			0x0003	/* 0x0001 | 0x0002 */
+#define PS3AV_RESBIT_1280x720P			0x0004
+#define PS3AV_RESBIT_1920x1080I			0x0008
+#define PS3AV_RESBIT_1920x1080P			0x4000
+#define PS3AV_RES_MASK_60			(PS3AV_RESBIT_720x480P \
+						| PS3AV_RESBIT_1280x720P \
+						| PS3AV_RESBIT_1920x1080I \
+						| PS3AV_RESBIT_1920x1080P)
+#define PS3AV_RES_MASK_50			(PS3AV_RESBIT_720x576P \
+						| PS3AV_RESBIT_1280x720P \
+						| PS3AV_RESBIT_1920x1080I \
+						| PS3AV_RESBIT_1920x1080P)
+
+#define PS3AV_MONITOR_TYPE_HDMI			1	/* HDMI */
+#define PS3AV_MONITOR_TYPE_DVI			2	/* DVI */
+#define PS3AV_DEFAULT_HDMI_VID_REG_60		PS3AV_CMD_VIDEO_VID_480P
+#define PS3AV_DEFAULT_AVMULTI_VID_REG_60	PS3AV_CMD_VIDEO_VID_480I
+#define PS3AV_DEFAULT_HDMI_VID_REG_50		PS3AV_CMD_VIDEO_VID_576P
+#define PS3AV_DEFAULT_AVMULTI_VID_REG_50	PS3AV_CMD_VIDEO_VID_576I
+#define PS3AV_DEFAULT_DVI_VID			PS3AV_CMD_VIDEO_VID_480P
+
+#define PS3AV_REGION_60				0x01
+#define PS3AV_REGION_50				0x02
+#define PS3AV_REGION_RGB			0x10
+
+#define get_status(buf)				(((__u32 *)buf)[2])
+#define PS3AV_HDR_SIZE				4	/* version + size */
+
+/* for video mode */
+#define PS3AV_MODE_MASK				0x000F
+#define PS3AV_MODE_HDCP_OFF			0x1000	/* Retail PS3 product doesn't support this */
+#define PS3AV_MODE_DITHER			0x0800
+#define PS3AV_MODE_FULL				0x0080
+#define PS3AV_MODE_DVI				0x0040
+#define PS3AV_MODE_RGB				0x0020
+
+#ifdef __KERNEL__
+/** command packet structure **/
+struct ps3av_send_hdr {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+};
+
+struct ps3av_reply_hdr {
+	u16 version;
+	u16 size;
+	u32 cid;
+	u32 status;
+};
+
+/* backend: initialization */
+struct ps3av_pkt_av_init {
+	struct ps3av_send_hdr send_hdr;
+	u32 event_bit;
+};
+
+/* backend: finalize */
+struct ps3av_pkt_av_fin {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* backend: get port */
+struct ps3av_pkt_av_get_hw_conf {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 status;
+	u16 num_of_hdmi;	/* out: number of hdmi */
+	u16 num_of_avmulti;	/* out: number of avmulti */
+	u16 num_of_spdif;	/* out: number of hdmi */
+	u16 reserved;
+};
+
+/* backend: get monitor info */
+struct ps3av_info_resolution {
+	u32 res_bits;
+	u32 native;
+};
+
+struct ps3av_info_cs {
+	u8 rgb;
+	u8 yuv444;
+	u8 yuv422;
+	u8 reserved;
+};
+
+struct ps3av_info_color {
+	u16 red_x;
+	u16 red_y;
+	u16 green_x;
+	u16 green_y;
+	u16 blue_x;
+	u16 blue_y;
+	u16 white_x;
+	u16 white_y;
+	u32 gamma;
+};
+
+struct ps3av_info_audio {
+	u8 type;
+	u8 max_num_of_ch;
+	u8 fs;
+	u8 sbit;
+};
+
+struct ps3av_info_monitor {
+	u8 avport;
+	u8 monitor_id[10];
+	u8 monitor_type;
+	u8 monitor_name[16];
+	struct ps3av_info_resolution res_60;
+	struct ps3av_info_resolution res_50;
+	struct ps3av_info_resolution res_other;
+	struct ps3av_info_resolution res_vesa;
+	struct ps3av_info_cs cs;
+	struct ps3av_info_color color;
+	u8 supported_ai;
+	u8 speaker_info;
+	u8 num_of_audio_block;
+	struct ps3av_info_audio audio[0];	/* 0 or more audio blocks */
+	u8 reserved[169];
+} __attribute__ ((packed));
+
+struct ps3av_pkt_av_get_monitor_info {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+	/* recv */
+	struct ps3av_info_monitor info;	/* out: monitor info */
+};
+
+/* backend: enable/disable event */
+struct ps3av_pkt_av_event {
+	struct ps3av_send_hdr send_hdr;
+	u32 event_bit;		/* in */
+};
+
+/* backend: video cs param */
+struct ps3av_pkt_av_video_cs {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 av_vid;		/* in: video resolution */
+	u16 av_cs_out;		/* in: output color space */
+	u16 av_cs_in;		/* in: input color space */
+	u8 dither;		/* in: dither bit length */
+	u8 bitlen_out;		/* in: bit length */
+	u8 super_white;		/* in: super white */
+	u8 aspect;		/* in: aspect ratio */
+};
+
+/* backend: video mute */
+struct ps3av_av_mute {
+	u16 avport;		/* in: avport */
+	u16 mute;		/* in: mute on/off */
+};
+
+struct ps3av_pkt_av_video_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
+};
+
+/* backend: video disable signal */
+struct ps3av_pkt_av_video_disable_sig {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+};
+
+/* backend: audio param */
+struct ps3av_audio_info_frame {
+	struct pb1_bit {
+		u8 ct:4;
+		u8 rsv:1;
+		u8 cc:3;
+	} pb1;
+	struct pb2_bit {
+		u8 rsv:3;
+		u8 sf:3;
+		u8 ss:2;
+	} pb2;
+	u8 pb3;
+	u8 pb4;
+	struct pb5_bit {
+		u8 dm:1;
+		u8 lsv:4;
+		u8 rsv:3;
+	} pb5;
+};
+
+struct ps3av_pkt_av_audio_param {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+	u8 mclk;		/* in: audio mclk */
+	u8 ns[3];		/* in: audio ns val */
+	u8 enable;		/* in: audio enable */
+	u8 swaplr;		/* in: audio swap */
+	u8 fifomap;		/* in: audio fifomap */
+	u8 inputctrl;		/* in: audio input ctrl */
+	u8 inputlen;		/* in: sample bit size */
+	u8 layout;		/* in: speaker layout param */
+	struct ps3av_audio_info_frame info;	/* in: info */
+	u8 chstat[5];		/* in: ch stat */
+};
+
+/* backend: audio_mute */
+struct ps3av_pkt_av_audio_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
+};
+
+/* backend: hdmi_mode */
+struct ps3av_pkt_av_hdmi_mode {
+	struct ps3av_send_hdr send_hdr;
+	u8 mode;		/* in: hdmi_mode */
+	u8 reserved0;
+	u8 reserved1;
+	u8 reserved2;
+};
+
+/* backend: tv_mute */
+struct ps3av_pkt_av_tv_mute {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport HDMI only */
+	u16 mute;		/* in: mute */
+};
+
+/* video: initialize */
+struct ps3av_pkt_video_init {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* video: mode setting */
+struct ps3av_pkt_video_mode {
+	struct ps3av_send_hdr send_hdr;
+	u32 video_head;		/* in: head */
+	u32 reserved;
+	u32 video_vid;		/* in: video resolution */
+	u16 reserved1;
+	u16 width;		/* in: width in pixel */
+	u16 reserved2;
+	u16 height;		/* in: height in pixel */
+	u32 pitch;		/* in: line size in byte */
+	u32 video_out_format;	/* in: out format */
+	u32 video_format;	/* in: input frame buffer format */
+	u8 reserved3;
+	u8 reserved4;
+	u16 video_order;	/* in: input RGB order */
+	u32 reserved5;
+};
+
+/* video: format */
+struct ps3av_pkt_video_format {
+	struct ps3av_send_hdr send_hdr;
+	u32 video_head;		/* in: head */
+	u32 video_format;	/* in: frame buffer format */
+	u16 reserved;
+	u16 video_order;	/* in: input RGB order */
+};
+
+/* video: pitch */
+struct ps3av_pkt_video_pitch {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u32 video_head;		/* in: head */
+	u32 pitch;		/* in: line size in byte */
+};
+
+/* audio: initialize */
+struct ps3av_pkt_audio_init {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* audio: mode setting */
+struct ps3av_pkt_audio_mode {
+	struct ps3av_send_hdr send_hdr;
+	u8 avport;		/* in: avport */
+	u8 reserved0[3];
+	u32 mask;		/* in: mask */
+	u32 audio_num_of_ch;	/* in: number of ch */
+	u32 audio_fs;		/* in: sampling freq */
+	u32 audio_word_bits;	/* in: sample bit size */
+	u32 audio_format;	/* in: audio output format */
+	u32 audio_source;	/* in: audio source */
+	u8 audio_enable[4];	/* in: audio enable */
+	u8 audio_swap[4];	/* in: audio swap */
+	u8 audio_map[4];	/* in: audio map */
+	u32 audio_layout;	/* in: speaker layout */
+	u32 audio_downmix;	/* in: audio downmix permission */
+	u32 audio_downmix_level;
+	u8 audio_cs_info[8];	/* in: IEC channel status */
+};
+
+/* audio: mute */
+struct ps3av_audio_mute {
+	u8 avport;		/* in: opt_port optical */
+	u8 reserved[3];
+	u32 mute;		/* in: mute */
+};
+
+struct ps3av_pkt_audio_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_audio_mute mute[PS3AV_OPT_PORT_MAX];
+};
+
+/* audio: active/inactive */
+struct ps3av_pkt_audio_active {
+	struct ps3av_send_hdr send_hdr;
+	u32 audio_port;		/* in: audio active/inactive port */
+};
+
+/* audio: SPDIF user bit */
+struct ps3av_pkt_audio_spdif_bit {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u8 avport;		/* in: avport SPDIF only */
+	u8 reserved[3];
+	u32 audio_port;		/* in: SPDIF only */
+	u32 spdif_bit_data[12];	/* in: user bit data */
+};
+
+/* audio: audio control */
+struct ps3av_pkt_audio_ctrl {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u32 audio_ctrl_id;	/* in: control id */
+	u32 audio_ctrl_data[4];	/* in: control data */
+};
+
+/* avb:param */
+struct ps3av_pkt_avb_param {
+	struct ps3av_send_hdr send_hdr;
+	u16 num_of_video_pkt;
+	u16 num_of_audio_pkt;
+	u16 num_of_av_video_pkt;
+	u16 num_of_av_audio_pkt;
+	struct ps3av_pkt_video_mode video[PS3AV_AVB_NUM_VIDEO];
+	struct ps3av_pkt_audio_mode audio[PS3AV_AVB_NUM_AUDIO];
+	struct ps3av_pkt_av_video_cs av_video[PS3AV_AVB_NUM_AV_VIDEO];
+	struct ps3av_pkt_av_audio_param av_audio[PS3AV_AVB_NUM_AV_AUDIO];
+};
+
+struct ps3av {
+	int available;
+	struct semaphore sem;
+	struct ps3_vuart_port_device *dev;
+
+	int region;
+	struct ps3av_pkt_av_get_hw_conf av_hw_conf;
+	u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX];
+	u32 opt_port[PS3AV_OPT_PORT_MAX];
+	u32 head[PS3AV_HEAD_MAX];
+	u32 audio_port;
+	atomic_t ps3av_mode;
+};
+
+/** command status **/
+#define PS3AV_STATUS_SUCCESS			0x0000	/* success */
+#define PS3AV_STATUS_RECEIVE_VUART_ERROR	0x0001	/* receive vuart error */
+#define PS3AV_STATUS_SYSCON_COMMUNICATE_FAIL	0x0002	/* syscon communication error */
+#define PS3AV_STATUS_INVALID_COMMAND		0x0003	/* obsolete invalid CID */
+#define PS3AV_STATUS_INVALID_PORT		0x0004	/* invalid port number */
+#define PS3AV_STATUS_INVALID_VID		0x0005	/* invalid video format */
+#define PS3AV_STATUS_INVALID_COLOR_SPACE	0x0006	/* invalid video colose space */
+#define PS3AV_STATUS_INVALID_FS			0x0007	/* invalid audio sampling freq */
+#define PS3AV_STATUS_INVALID_AUDIO_CH		0x0008	/* invalid audio channel number */
+#define PS3AV_STATUS_UNSUPPORTED_VERSION	0x0009	/* version mismatch  */
+#define PS3AV_STATUS_INVALID_SAMPLE_SIZE	0x000a	/* invalid audio sample bit size */
+#define PS3AV_STATUS_FAILURE			0x000b	/* other failures */
+#define PS3AV_STATUS_UNSUPPORTED_COMMAND	0x000c	/* unsupported cid */
+#define PS3AV_STATUS_BUFFER_OVERFLOW		0x000d	/* write buffer overflow */
+#define PS3AV_STATUS_INVALID_VIDEO_PARAM	0x000e	/* invalid video param */
+#define PS3AV_STATUS_NO_SEL			0x000f	/* not exist selector */
+#define PS3AV_STATUS_INVALID_AV_PARAM		0x0010	/* invalid backend param */
+#define PS3AV_STATUS_INVALID_AUDIO_PARAM	0x0011	/* invalid audio param */
+#define PS3AV_STATUS_UNSUPPORTED_HDMI_MODE	0x0012	/* unsupported hdmi mode */
+#define PS3AV_STATUS_NO_SYNC_HEAD		0x0013	/* sync head failed */
+
+extern void ps3av_set_hdr(u32, u16, struct ps3av_send_hdr *);
+extern int ps3av_do_pkt(u32, u16, size_t, struct ps3av_send_hdr *);
+
+extern int ps3av_cmd_init(void);
+extern int ps3av_cmd_fin(void);
+extern int ps3av_cmd_av_video_mute(int, u32 *, u32);
+extern int ps3av_cmd_av_video_disable_sig(u32);
+extern int ps3av_cmd_av_tv_mute(u32, u32);
+extern int ps3av_cmd_enable_event(void);
+extern int ps3av_cmd_av_hdmi_mode(u8);
+extern u8 *ps3av_cmd_set_av_video_cs(u8 *, u32, int, int, int, u32);
+extern u8 *ps3av_cmd_set_video_mode(u8 *, u32, int, int, u32);
+extern int ps3av_cmd_video_format_black(u32, u32, u32);
+extern int ps3av_cmd_av_audio_mute(int, u32 *, u32);
+extern u8 *ps3av_cmd_set_av_audio_param(u8 *, u32,
+					const struct ps3av_pkt_audio_mode *,
+					u32);
+extern void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *, u32, u32,
+				     u32, u32, u32, u32);
+extern int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *);
+extern int ps3av_cmd_audio_mute(int, u32 *, u32);
+extern int ps3av_cmd_audio_active(int, u32);
+extern int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *, u32);
+extern int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *);
+extern int ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *);
+extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
+					    u32);
+extern int ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *);
+
+extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
+			     const void *buf, unsigned long size);
+extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
+			    unsigned long size, int timeout);
+
+extern int ps3av_set_video_mode(u32, int);
+extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
+extern int ps3av_set_mode(u32, int);
+extern int ps3av_get_mode(void);
+extern int ps3av_get_scanmode(int);
+extern int ps3av_get_refresh_rate(int);
+extern int ps3av_video_mode2res(u32, u32 *, u32 *);
+extern int ps3av_video_mute(int);
+extern int ps3av_audio_mute(int);
+extern int ps3av_dev_open(void);
+extern int ps3av_dev_close(void);
+#endif	/* __KERNEL__ */
+
+#endif	/* _PS3AV_H_ */

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 1/9] ps3: AV Settings Driver
@ 2007-01-25 17:48   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:48 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

Add the PS3 AV Settings Driver.

The AV Settings driver is used to control Audio and Video settings.
It communicates with the policy manager through the virtual uart.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 arch/powerpc/platforms/ps3/Kconfig |   10 
 drivers/ps3/Makefile               |    1 
 drivers/ps3/ps3av.c                |  998 +++++++++++++++++++++++++++++++++++
 drivers/ps3/ps3av_cmd.c            | 1052 +++++++++++++++++++++++++++++++++++++
 include/asm-powerpc/ps3av.h        |  716 +++++++++++++++++++++++++
 5 files changed, 2777 insertions(+)

--- ps3-linux.orig/arch/powerpc/platforms/ps3/Kconfig
+++ ps3-linux/arch/powerpc/platforms/ps3/Kconfig
@@ -51,4 +51,14 @@ config PS3_VUART
 	  including the System Manager and AV Settings.  In
 	  general, all users will say Y.
 
+config PS3_PS3AV
+	tristate "PS3 AV controller support"
+	default y
+	depends on PS3_VUART
+	help
+	  Include support for the PS3 Platform AV Settings device.
+
+	  This support is required for graphics and sound. In
+	  general, all users will say Y or M.
+
 endmenu
--- ps3-linux.orig/drivers/ps3/Makefile
+++ ps3-linux/drivers/ps3/Makefile
@@ -1,2 +1,3 @@
 obj-y += system-bus.o
 obj-$(CONFIG_PS3_VUART) += vuart.o
+obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
--- /dev/null
+++ ps3-linux/drivers/ps3/ps3av.c
@@ -0,0 +1,998 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ * AV backend support for PS3
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/kernel.h>
+#include <linux/ioctl.h>
+#include <linux/mutex.h>
+#include <asm/lv1call.h>
+#include <asm/atomic.h>
+#include <asm/ps3av.h>
+#include <asm/ps3.h>
+
+#include "vuart.h"
+
+#ifdef PS3AV_DEBUG
+#define DPRINTK(fmt, args...) \
+	do { printk("ps3av " fmt, ## args); } while (0)
+#else
+#define DPRINTK(fmt, args...) do { } while (0)
+#endif
+
+#define BUFSIZE          4096	/* vuart buf size */
+#define PS3AV_BUF_SIZE   512	/* max packet size */
+
+static int timeout = 5000;	/* in msec ( 5 sec ) */
+module_param(timeout, int, 0644);
+
+static struct ps3av ps3av;
+
+static DEFINE_MUTEX(ps3av_mutex);
+static int ps3av_open_count = 0;
+
+/* color space */
+#define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
+#define RGB8   PS3AV_CMD_VIDEO_CS_RGB_8
+/* format */
+#define XRGB   PS3AV_CMD_VIDEO_FMT_X8R8G8B8
+/* aspect */
+#define A_N    PS3AV_CMD_AV_ASPECT_4_3
+#define A_W    PS3AV_CMD_AV_ASPECT_16_9
+static const struct avset_video_mode {
+	u32 cs;
+	u32 fmt;
+	u32 vid;
+	u32 aspect;
+	u32 x;
+	u32 y;
+	u32 interlace;
+	u32 freq;
+} video_mode_table[] = {
+	{     0, }, /* auto */
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I,       A_N,  720,  480, 1, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P,       A_N,  720,  480, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ,  A_N, 1280,  720, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I,       A_N,  720,  576, 1, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P,       A_N,  720,  576, 0, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ,  A_N, 1280,  720, 0, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA,       A_W, 1280,  768, 0, 60},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA,       A_N, 1280, 1024, 0, 60},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA,      A_W, 1920, 1200, 0, 60},
+};
+
+/* supported CIDs */
+static u32 cmd_table[] = {
+	/* init */
+	PS3AV_CID_AV_INIT,
+	PS3AV_CID_AV_FIN,
+	PS3AV_CID_VIDEO_INIT,
+	PS3AV_CID_AUDIO_INIT,
+
+	/* set */
+	PS3AV_CID_AV_ENABLE_EVENT,
+	PS3AV_CID_AV_DISABLE_EVENT,
+
+	PS3AV_CID_AV_VIDEO_CS,
+	PS3AV_CID_AV_VIDEO_MUTE,
+	PS3AV_CID_AV_VIDEO_DISABLE_SIG,
+	PS3AV_CID_AV_AUDIO_PARAM,
+	PS3AV_CID_AV_AUDIO_MUTE,
+	PS3AV_CID_AV_HDMI_MODE,
+	PS3AV_CID_AV_TV_MUTE,
+
+	PS3AV_CID_VIDEO_MODE,
+	PS3AV_CID_VIDEO_FORMAT,
+	PS3AV_CID_VIDEO_PITCH,
+
+	PS3AV_CID_AUDIO_MODE,
+	PS3AV_CID_AUDIO_MUTE,
+	PS3AV_CID_AUDIO_ACTIVE,
+	PS3AV_CID_AUDIO_INACTIVE,
+	PS3AV_CID_AVB_PARAM,
+
+	/* get */
+	PS3AV_CID_AV_GET_HW_CONF,
+	PS3AV_CID_AV_GET_MONITOR_INFO,
+
+	/* event */
+	PS3AV_CID_EVENT_UNPLUGGED,
+	PS3AV_CID_EVENT_PLUGGED,
+	PS3AV_CID_EVENT_HDCP_DONE,
+	PS3AV_CID_EVENT_HDCP_FAIL,
+	PS3AV_CID_EVENT_HDCP_AUTH,
+	PS3AV_CID_EVENT_HDCP_ERROR,
+
+	0
+};
+
+#define PS3AV_EVENT_CMD_MASK           0x10000000
+#define PS3AV_EVENT_ID_MASK            0x0000ffff
+#define PS3AV_CID_MASK                 0xffffffff
+#define PS3AV_REPLY_BIT                0x80000000
+
+#define ps3av_event_get_port_id(cid)   ((cid >> 16) & 0xff)
+
+static u32 *ps3av_search_cmd_table(u32 cid, u32 mask)
+{
+	u32 *table;
+	int i;
+
+	table = cmd_table;
+	for (i = 0;; table++, i++) {
+		if ((*table & mask) == (cid & mask))
+			break;
+		if (*table == 0)
+			return NULL;
+	}
+	return table;
+}
+
+static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
+{
+	u32 *table;
+
+	if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
+		table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
+		if (table)
+			DPRINTK
+			    ("recv event packet cid:%08x port:0x%x size:%d\n",
+			     hdr->cid, ps3av_event_get_port_id(hdr->cid),
+			     hdr->size);
+		else
+			printk(KERN_ERR
+			       "%s: failed event packet, cid:%08x size:%d\n",
+			       __FUNCTION__, hdr->cid, hdr->size);
+		return 1;	/* receive event packet */
+	}
+	return 0;
+}
+
+static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
+			      struct ps3av_reply_hdr *recv_buf, int write_len,
+			      int read_len)
+{
+	int res;
+	u32 cmd;
+	int event;
+
+	if (!ps3av.available)
+		return -ENODEV;
+
+	/* send pkt */
+	res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
+	if (res < 0) {
+		DPRINTK("%s: ps3av_vuart_write() failed (result=%d)\n",
+			__FUNCTION__, res);
+		return res;
+	}
+
+	/* recv pkt */
+	cmd = send_buf->cid;
+	do {
+		/* read header */
+		res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
+				       timeout);
+		if (res != PS3AV_HDR_SIZE) {
+			DPRINTK("%s: ps3av_vuart_read() failed (result=%d)\n",
+				__FUNCTION__, res);
+			return res;
+		}
+
+		/* read body */
+		res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
+				       recv_buf->size, timeout);
+		if (res < 0) {
+			DPRINTK("%s: ps3av_vuart_read() failed (result=%d)\n",
+				__FUNCTION__, res);
+			return res;
+		}
+		res += PS3AV_HDR_SIZE;	/* total len */
+		event = ps3av_parse_event_packet(recv_buf);
+		/* ret > 0 event packet */
+	} while (event);
+
+	if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
+		DPRINTK("%s: reply err (result=%x)\n",
+			__FUNCTION__, recv_buf->cid);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf,
+				      const struct ps3av_reply_hdr *recv_buf,
+				      int user_buf_size)
+{
+	int return_len;
+
+	if (recv_buf->version != PS3AV_VERSION) {
+		DPRINTK("reply_packet invalid version:%x\n",
+			recv_buf->version);
+		return -EFAULT;
+	}
+	return_len = recv_buf->size + PS3AV_HDR_SIZE;
+	if (return_len > user_buf_size)
+		return_len = user_buf_size;
+	memcpy(cmd_buf, recv_buf, return_len);
+	return 0;		/* success */
+}
+
+void ps3av_set_hdr(u32 cid, u16 size, struct ps3av_send_hdr *hdr)
+{
+	hdr->version = PS3AV_VERSION;
+	hdr->size = size - PS3AV_HDR_SIZE;
+	hdr->cid = cid;
+}
+
+int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
+		 struct ps3av_send_hdr *buf)
+{
+	int res = 0;
+	union {
+		struct ps3av_reply_hdr reply_hdr;
+		u8 raw[PS3AV_BUF_SIZE];
+	} recv_buf;
+
+	u32 *table;
+
+	BUG_ON(!ps3av.available);
+
+	if (down_interruptible(&ps3av.sem)) {
+		printk(KERN_ERR "%s:sem failed cid:%x \n", __FUNCTION__, cid);
+		return -ERESTARTSYS;
+	}
+
+	table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
+	if (table == NULL) {
+		printk(KERN_ERR "%s: invalid_cid:%x\n", __FUNCTION__, cid);
+		res = -EINVAL;
+		goto err;
+	}
+	if (send_len < PS3AV_HDR_SIZE) {
+		printk(KERN_ERR "%s: invalid send_len:%d\n", __FUNCTION__,
+		       send_len);
+		goto err;
+	}
+
+	/* create header */
+	ps3av_set_hdr(cid, send_len, buf);
+
+	if (usr_buf_size < send_len || usr_buf_size > PS3AV_BUF_SIZE) {
+		printk(KERN_ERR "%s: invalid packet size:%ld\n", __FUNCTION__,
+		       usr_buf_size);
+		goto err;
+	}
+
+	/* send packet via vuart */
+	res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
+				 usr_buf_size);
+	if (res < 0) {
+		printk(KERN_ERR
+		       "%s: ps3av_send_cmd_pkt() failed (result=%d)\n",
+		       __FUNCTION__, res);
+		goto err;
+	}
+
+	/* process reply packet */
+	res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
+					 usr_buf_size);
+	if (res < 0) {
+		printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
+		       __FUNCTION__, res);
+		goto err;
+	}
+
+	up(&ps3av.sem);
+	return 0;
+
+      err:
+	up(&ps3av.sem);
+	printk(KERN_ERR "%s: failed cid:%x res:%d\n", __FUNCTION__, cid, res);
+	return res;
+}
+
+static int ps3av_set_av_video_mute(u32 mute)
+{
+	int i, num_of_av_port, res;
+
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi
+	    + ps3av.av_hw_conf.num_of_avmulti;
+	/* video mute on */
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int ps3av_set_video_disable_sig(u32 id)
+{
+	int i, num_of_hdmi_port, num_of_av_port, res;
+
+	num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+	    ps3av.av_hw_conf.num_of_avmulti;
+
+	/* tv mute */
+	for (i = 0; i < num_of_hdmi_port; i++) {
+		res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+					   PS3AV_CMD_MUTE_ON);
+		if (res < 0)
+			return -1;
+	}
+	msleep(100);
+
+	/* video mute on */
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
+		if (res < 0)
+			return -1;
+		if (i < num_of_hdmi_port) {
+			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+						   PS3AV_CMD_MUTE_OFF);
+			if (res < 0)
+				return -1;
+		}
+	}
+	msleep(300);
+
+	return 0;
+}
+
+static int ps3av_set_audio_mute(u32 mute)
+{
+	int i, num_of_av_port, num_of_opt_port, res;
+
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+	    ps3av.av_hw_conf.num_of_avmulti;
+	num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
+
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+	for (i = 0; i < num_of_opt_port; i++) {
+		res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
+{
+	struct ps3av_pkt_avb_param avb_param;
+	int i, num_of_audio, vid, res;
+	struct ps3av_pkt_audio_mode audio_mode;
+	u8 *param_p;
+	u32 len;
+
+	num_of_audio = ps3av.av_hw_conf.num_of_hdmi
+	    + ps3av.av_hw_conf.num_of_avmulti + ps3av.av_hw_conf.num_of_spdif;
+
+	avb_param.num_of_video_pkt = 0;
+	avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO;	/* allways 0 */
+	avb_param.num_of_av_video_pkt = 0;
+	avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
+
+	vid = video_mode_table[atomic_read(&ps3av.ps3av_mode)].vid;
+
+	/* audio mute */
+	ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
+
+	/* audio inactive */
+	res = ps3av_cmd_audio_active(0, ps3av.audio_port);
+	if (res < 0)
+		DPRINTK("ps3av_cmd_audio_active OFF failed\n");
+
+	param_p = (u8 *) &avb_param.video;
+	/* audio_pkt */
+	for (i = 0; i < num_of_audio; i++) {
+		ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
+					 word_bits, format, source);
+		if (i < ps3av.av_hw_conf.num_of_hdmi) {
+			/* hdmi only */
+			param_p = ps3av_cmd_set_av_audio_param(param_p,
+							       ps3av.av_port[i],
+							       &audio_mode,
+							       vid);
+		}
+		/* audio_mode pkt should be sent separately */
+		res = ps3av_cmd_audio_mode(&audio_mode);
+		if (res < 0)
+			DPRINTK("ps3av_cmd_audio_mode failed, port:%x\n", i);
+	}
+
+	/* send command using avb pkt */
+	len = param_p - (u8 *) & avb_param;
+	res = ps3av_cmd_avb_param(&avb_param, len);
+	if (res < 0)
+		DPRINTK("ps3av_cmd_avb_param failed\n");
+
+	/* audio mute */
+	ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
+
+	/* audio active */
+	res = ps3av_cmd_audio_active(1, ps3av.audio_port);
+	if (res < 0)
+		DPRINTK("ps3av_cmd_audio_active ON failed\n");
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3av_set_audio_mode);
+
+static int ps3av_set_videomode(u32 id)
+{
+	struct ps3av_pkt_avb_param avb_param;
+	int i;
+	u8 *param_p;
+	u32 len, av_video_cs = 0;
+	const struct avset_video_mode *video_mode;
+	int old_mode, res, event = 0;
+
+	old_mode = ps3av_get_mode();
+
+	video_mode = &video_mode_table[id & PS3AV_MODE_MASK];
+
+	avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO;	/* num of head */
+	avb_param.num_of_audio_pkt = 0;
+	avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
+	    ps3av.av_hw_conf.num_of_avmulti;
+	avb_param.num_of_av_audio_pkt = 0;
+
+	/* send command packet */
+	if (event) {
+		/* event enable */
+		res = ps3av_cmd_enable_event();
+		if (res < 0)
+			DPRINTK("ps3av_cmd_enable_event failed \n");
+	}
+
+	/* av video mute */
+	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
+	/* video signal off */
+	ps3av_set_video_disable_sig(id);
+
+	/* Retail PS3 product doesn't support this */
+	if (id & PS3AV_MODE_HDCP_OFF) {
+		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
+		if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+			DPRINTK("Not supported\n");
+		else if (res)
+			DPRINTK("ps3av_cmd_av_hdmi_mode failed\n");
+	} else if (old_mode & PS3AV_MODE_HDCP_OFF) {
+		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
+		if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+			DPRINTK("ps3av_cmd_av_hdmi_mode failed\n");
+	}
+
+	param_p = (u8 *) & avb_param.video;
+	/* video_pkt */
+	for (i = 0; i < avb_param.num_of_video_pkt; i++)
+		param_p = ps3av_cmd_set_video_mode(param_p,
+						   ps3av.head[i],
+						   video_mode->vid,
+						   video_mode->fmt, id);
+	/* av_video_pkt */
+	for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
+		if (id & PS3AV_MODE_DVI || id & PS3AV_MODE_RGB)
+			av_video_cs = RGB8;
+		else
+			av_video_cs = video_mode->cs;
+#ifndef PS3AV_HDMI_YUV
+		if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
+		    ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
+			av_video_cs = RGB8;	/* use RGB for HDMI */
+#endif
+		param_p = ps3av_cmd_set_av_video_cs(param_p, ps3av.av_port[i],
+						    video_mode->vid,
+						    av_video_cs,
+						    video_mode->aspect, id);
+	}
+	/* send command using avb pkt */
+	len = param_p - (u8 *) & avb_param;
+	res = ps3av_cmd_avb_param(&avb_param, len);
+	if (res == PS3AV_STATUS_NO_SYNC_HEAD)
+		printk(KERN_WARNING
+		       "%s: Command failed. Please try your request again. \n",
+		       __FUNCTION__);
+	else if (res)
+		DPRINTK("ps3av_cmd_avb_param failed\n");
+
+	msleep(1500);
+	/* av video mute */
+	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);
+
+	return 0;
+}
+
+static int ps3av_vid2table_id(int vid)
+{
+	int i;
+
+	for (i = 1; i < ARRAY_SIZE(video_mode_table); i++)
+		if (video_mode_table[i].vid == vid)
+			return i;
+	return -1;
+}
+
+static int ps3av_resbit2vid(u32 res_50, u32 res_60)
+{
+	int vid = -1;
+
+	if (res_50 > res_60) {	/* if res_50 == res_60, res_60 will be used */
+		if (res_50 & PS3AV_RESBIT_1920x1080P)
+			vid = PS3AV_CMD_VIDEO_VID_1080P_50HZ;
+		else if (res_50 & PS3AV_RESBIT_1920x1080I)
+			vid = PS3AV_CMD_VIDEO_VID_1080I_50HZ;
+		else if (res_50 & PS3AV_RESBIT_1280x720P)
+			vid = PS3AV_CMD_VIDEO_VID_720P_50HZ;
+		else if (res_50 & PS3AV_RESBIT_720x576P)
+			vid = PS3AV_CMD_VIDEO_VID_576P;
+		else
+			vid = -1;
+	} else {
+		if (res_60 & PS3AV_RESBIT_1920x1080P)
+			vid = PS3AV_CMD_VIDEO_VID_1080P_60HZ;
+		else if (res_60 & PS3AV_RESBIT_1920x1080I)
+			vid = PS3AV_CMD_VIDEO_VID_1080I_60HZ;
+		else if (res_60 & PS3AV_RESBIT_1280x720P)
+			vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+		else if (res_60 & PS3AV_RESBIT_720x480P)
+			vid = PS3AV_CMD_VIDEO_VID_480P;
+		else
+			vid = -1;
+	}
+	return vid;
+}
+
+static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info)
+{
+	u32 res_50, res_60;
+	int vid = -1;
+
+	if (info->monitor_type != PS3AV_MONITOR_TYPE_HDMI)
+		return -1;
+
+	/* check native resolution */
+	res_50 = info->res_50.native & PS3AV_RES_MASK_50;
+	res_60 = info->res_60.native & PS3AV_RES_MASK_60;
+	if (res_50 || res_60) {
+		vid = ps3av_resbit2vid(res_50, res_60);
+		return vid;
+	}
+
+	/* check resolution */
+	res_50 = info->res_50.res_bits & PS3AV_RES_MASK_50;
+	res_60 = info->res_60.res_bits & PS3AV_RES_MASK_60;
+	if (res_50 || res_60) {
+		vid = ps3av_resbit2vid(res_50, res_60);
+		return vid;
+	}
+
+	if (ps3av.region & PS3AV_REGION_60)
+		vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+	else
+		vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+	return vid;
+}
+
+static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf,
+				int boot)
+{
+	int i, res, vid = -1, dvi = 0, rgb = 0;
+	struct ps3av_pkt_av_get_monitor_info monitor_info;
+	struct ps3av_info_monitor *info;
+
+	/* get vid for hdmi */
+	for (i = 0; i < av_hw_conf->num_of_hdmi; i++) {
+		res = ps3av_cmd_video_get_monitor_info(&monitor_info,
+						       PS3AV_CMD_AVPORT_HDMI_0 +
+						       i);
+		if (res < 0)
+			return -1;
+
+#ifdef PS3AV_DEBUG
+		ps3av_cmd_av_monitor_info_dump(&monitor_info);
+#endif
+		info = &monitor_info.info;
+		/* check DVI */
+		if (info->monitor_type == PS3AV_MONITOR_TYPE_DVI) {
+			dvi = PS3AV_MODE_DVI;
+			break;
+		}
+		/* check HDMI */
+		vid = ps3av_hdmi_get_vid(info);
+		if (vid != -1) {
+			/* got valid vid */
+			break;
+		}
+	}
+
+	if (dvi) {
+		/* DVI mode */
+		vid = PS3AV_DEFAULT_DVI_VID;
+	} else if (vid == -1) {
+		/* no HDMI interface or HDMI is off */
+		if (ps3av.region & PS3AV_REGION_60)
+			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
+		else
+			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
+		if (ps3av.region & PS3AV_REGION_RGB)
+			rgb = PS3AV_MODE_RGB;
+	} else if (boot) {
+		/* HDMI: using DEFAULT HDMI_VID while booting up */
+		info = &monitor_info.info;
+		if (ps3av.region & PS3AV_REGION_60) {
+			if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			else {
+				/* default */
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			}
+		} else {
+			if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			else if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			else {
+				/* default */
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			}
+		}
+	}
+
+	return (ps3av_vid2table_id(vid) | dvi | rgb);
+}
+
+static int ps3av_get_hw_conf(struct ps3av *ps3av)
+{
+	int i, j, k, res;
+
+	/* get av_hw_conf */
+	res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf);
+	if (res < 0)
+		return -1;
+
+#ifdef PS3AV_DEBUG
+	ps3av_cmd_av_hw_conf_dump(&ps3av->av_hw_conf);
+#endif
+
+	for (i = 0; i < PS3AV_HEAD_MAX; i++)
+		ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i;
+	for (i = 0; i < PS3AV_OPT_PORT_MAX; i++)
+		ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i;
+	for (i = 0; i < ps3av->av_hw_conf.num_of_hdmi; i++)
+		ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i;
+	for (j = 0; j < ps3av->av_hw_conf.num_of_avmulti; j++)
+		ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j;
+	for (k = 0; k < ps3av->av_hw_conf.num_of_spdif; k++)
+		ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k;
+
+	/* set all audio port */
+	ps3av->audio_port = PS3AV_CMD_AUDIO_PORT_HDMI_0
+	    | PS3AV_CMD_AUDIO_PORT_HDMI_1
+	    | PS3AV_CMD_AUDIO_PORT_AVMULTI_0
+	    | PS3AV_CMD_AUDIO_PORT_SPDIF_0 | PS3AV_CMD_AUDIO_PORT_SPDIF_1;
+
+	return 0;
+}
+
+/* set mode using id */
+int ps3av_set_video_mode(u32 id, int boot)
+{
+	int size;
+	u32 option;
+	u32 old_id;
+
+	size = ARRAY_SIZE(video_mode_table);
+	if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
+		DPRINTK("%s: error id :%d\n", __FUNCTION__, id);
+		return -1;
+	}
+
+	/* auto mode */
+	option = id & ~PS3AV_MODE_MASK;
+	if ((id & PS3AV_MODE_MASK) == 0) {
+		id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+		if (id < 1) {
+			printk(KERN_ERR "%s: invalid id :%d\n", __FUNCTION__,
+			       id);
+			return -1;
+		}
+		id |= option;
+	}
+
+	/* set videomode */
+	old_id = atomic_read(&ps3av.ps3av_mode);
+	atomic_set(&ps3av.ps3av_mode, id);
+	if (ps3av_set_videomode(id))
+		atomic_set(&ps3av.ps3av_mode, old_id);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3av_set_video_mode);
+
+int ps3av_set_mode(u32 id, int boot)
+{
+	int res;
+
+	res = ps3av_set_video_mode(id, boot);
+	if (res)
+		return -1;
+
+	res = ps3av_set_audio_mode(PS3AV_CMD_AUDIO_NUM_OF_CH_2,
+				   PS3AV_CMD_AUDIO_FS_48K,
+				   PS3AV_CMD_AUDIO_WORD_BITS_16,
+				   PS3AV_CMD_AUDIO_FORMAT_PCM,
+				   PS3AV_CMD_AUDIO_SOURCE_SERIAL);
+	if (res)
+		return -1;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3av_set_mode);
+
+int ps3av_get_mode(void)
+{
+	return atomic_read(&ps3av.ps3av_mode);
+}
+
+EXPORT_SYMBOL(ps3av_get_mode);
+
+int ps3av_get_scanmode(int id)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -1;
+	}
+	return video_mode_table[id].interlace;
+}
+
+EXPORT_SYMBOL(ps3av_get_scanmode);
+
+int ps3av_get_refresh_rate(int id)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -1;
+	}
+	return video_mode_table[id].freq;
+}
+
+EXPORT_SYMBOL(ps3av_get_refresh_rate);
+
+/* get resolution by video_mode */
+int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -1;
+	}
+	*xres = video_mode_table[id].x;
+	*yres = video_mode_table[id].y;
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3av_video_mode2res);
+
+/* mute */
+int ps3av_video_mute(int mute)
+{
+	return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON
+					    : PS3AV_CMD_MUTE_OFF);
+}
+
+EXPORT_SYMBOL(ps3av_video_mute);
+
+int ps3av_audio_mute(int mute)
+{
+	return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
+					 : PS3AV_CMD_MUTE_OFF);
+}
+
+EXPORT_SYMBOL(ps3av_audio_mute);
+
+int ps3av_dev_open(void)
+{
+	int status = 0;
+
+	mutex_lock(&ps3av_mutex);
+	if (!ps3av_open_count++) {
+		status = lv1_gpu_open(0);
+		if (status) {
+			printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
+			       __FUNCTION__, status);
+			ps3av_open_count--;
+		}
+	}
+	mutex_unlock(&ps3av_mutex);
+
+	return status;
+}
+
+EXPORT_SYMBOL(ps3av_dev_open);
+
+int ps3av_dev_close(void)
+{
+	int status = 0;
+
+	mutex_lock(&ps3av_mutex);
+	if (ps3av_open_count <= 0) {
+		printk(KERN_ERR "%s: GPU already closed\n", __FUNCTION__);
+		status = -1;
+	} else if (!--ps3av_open_count) {
+		status = lv1_gpu_close();
+		if (status)
+			printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
+			       __FUNCTION__, status);
+	}
+	mutex_unlock(&ps3av_mutex);
+
+	return status;
+}
+
+EXPORT_SYMBOL(ps3av_dev_close);
+
+static int ps3av_at_exit(struct notifier_block *self,
+			 unsigned long state, void *data)
+{
+	/* fin avsetting modules */
+	ps3av_cmd_fin();
+
+	if (!ps3av.available)
+		return NOTIFY_OK;
+
+	ps3av.available = 0;
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block ps3av_reboot_nb = {
+	.notifier_call = ps3av_at_exit
+};
+
+static int ps3av_probe(struct ps3_vuart_port_device *dev)
+{
+	int res;
+	u32 id;
+
+	DPRINTK("init ...\n");
+	DPRINTK("  timeout=%d\n", timeout);
+
+	memset(&ps3av, 0, sizeof(ps3av));
+
+	init_MUTEX(&ps3av.sem);
+	atomic_set(&ps3av.ps3av_mode, 0);
+	ps3av.dev = dev;
+
+	ps3av.available = 1;
+	switch (ps3_os_area_get_av_multi_out()) {
+	case PS3_PARAM_AV_MULTI_OUT_NTSC:
+		ps3av.region = PS3AV_REGION_60;
+		break;
+	case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
+	case PS3_PARAM_AV_MULTI_OUT_SECAM:
+		ps3av.region = PS3AV_REGION_50;
+		break;
+	case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
+		ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
+		break;
+	default:
+		ps3av.region = PS3AV_REGION_60;
+		break;
+	}
+	register_reboot_notifier(&ps3av_reboot_nb);
+
+	/* init avsetting modules */
+	res = ps3av_cmd_init();
+	if (res < 0)
+		printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __FUNCTION__,
+		       res);
+
+	ps3av_get_hw_conf(&ps3av);
+	id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
+	atomic_set(&ps3av.ps3av_mode, id);
+
+	DPRINTK("init...done\n");
+
+	return 0;
+}
+
+static int ps3av_remove(struct ps3_vuart_port_device *dev)
+{
+	if (ps3av.available) {
+		ps3av_cmd_fin();
+		unregister_reboot_notifier(&ps3av_reboot_nb);
+	}
+	ps3av.available = 0;
+
+	return 0;
+}
+
+static struct ps3_vuart_port_driver ps3av_driver = {
+	.match_id = PS3_MATCH_ID_AV_SETTINGS,
+	.core = {
+		.name = "ps3_av",
+	},
+	.probe = ps3av_probe,
+	.remove = ps3av_remove,
+};
+
+static struct ps3_vuart_port_device ps3av_dev = {
+	.match_id = PS3_MATCH_ID_AV_SETTINGS
+};
+
+static int ps3av_module_init(void)
+{
+	int error = ps3_vuart_port_driver_register(&ps3av_driver);
+	if (error) {
+		printk(KERN_ERR
+		       "%s: ps3_vuart_port_driver_register failed %d\n",
+		       __FUNCTION__, error);
+		return error;
+	}
+
+	error = ps3_vuart_port_device_register(&ps3av_dev);
+	if (error)
+		printk(KERN_ERR
+		       "%s: ps3_vuart_port_device_register failed %d\n",
+		       __FUNCTION__, error);
+
+	return error;
+}
+
+static void __exit ps3av_module_exit(void)
+{
+	device_unregister(&ps3av_dev.core);
+	ps3_vuart_port_driver_unregister(&ps3av_driver);
+}
+
+subsys_initcall(ps3av_module_init);
+module_exit(ps3av_module_exit);
--- /dev/null
+++ ps3-linux/drivers/ps3/ps3av_cmd.c
@@ -0,0 +1,1052 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ * AV backend support for PS3
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/ps3av.h>
+#include <asm/ps3.h>
+
+#include "vuart.h"
+
+#ifdef PS3AV_DEBUG
+#define DPRINTK(fmt, args...) \
+	do { printk("ps3av " fmt, ## args); } while (0)
+#else
+#define DPRINTK(fmt, args...) do { } while (0)
+#endif
+
+static const struct video_fmt {
+	u32 format;
+	u32 order;
+} ps3av_video_fmt_table[] = {
+	{ PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_RGB },
+	{ PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_BGR },
+};
+
+static u32 ps3av_cs_video2av(int cs)
+{
+	u32 res = 0;
+
+	switch (cs) {
+	case PS3AV_CMD_VIDEO_CS_RGB_8:
+	case PS3AV_CMD_VIDEO_CS_RGB_10:
+	case PS3AV_CMD_VIDEO_CS_RGB_12:
+		res = PS3AV_CMD_AV_CS_RGB_8;
+		break;
+	case PS3AV_CMD_VIDEO_CS_YUV444_8:
+	case PS3AV_CMD_VIDEO_CS_YUV444_10:
+	case PS3AV_CMD_VIDEO_CS_YUV444_12:
+		res = PS3AV_CMD_AV_CS_YUV444_8;
+		break;
+	case PS3AV_CMD_VIDEO_CS_YUV422_8:
+	case PS3AV_CMD_VIDEO_CS_YUV422_10:
+	case PS3AV_CMD_VIDEO_CS_YUV422_12:
+		res = PS3AV_CMD_AV_CS_YUV422_8;
+		break;
+	case PS3AV_CMD_VIDEO_CS_XVYCC_8:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_10:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_12:
+		res = PS3AV_CMD_AV_CS_XVYCC_8;
+		break;
+	default:
+		res = PS3AV_CMD_AV_CS_RGB_8;
+		break;
+	}
+	return res;
+}
+
+static u32 ps3av_cs_video2av_bitlen(int cs)
+{
+	u32 res = 0;
+
+	switch (cs) {
+	case PS3AV_CMD_VIDEO_CS_RGB_8:
+	case PS3AV_CMD_VIDEO_CS_YUV444_8:
+	case PS3AV_CMD_VIDEO_CS_YUV422_8:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_8:
+		res = PS3AV_CMD_AV_CS_8;
+		break;
+	case PS3AV_CMD_VIDEO_CS_RGB_10:
+	case PS3AV_CMD_VIDEO_CS_YUV444_10:
+	case PS3AV_CMD_VIDEO_CS_YUV422_10:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_10:
+		res = PS3AV_CMD_AV_CS_10;
+		break;
+	case PS3AV_CMD_VIDEO_CS_RGB_12:
+	case PS3AV_CMD_VIDEO_CS_YUV444_12:
+	case PS3AV_CMD_VIDEO_CS_YUV422_12:
+	case PS3AV_CMD_VIDEO_CS_XVYCC_12:
+		res = PS3AV_CMD_AV_CS_12;
+		break;
+	default:
+		res = PS3AV_CMD_AV_CS_8;
+		break;
+	}
+	return res;
+}
+
+static u32 ps3av_vid_video2av(int vid)
+{
+	u32 res = 0;
+
+	switch (vid) {
+	case PS3AV_CMD_VIDEO_VID_480I:
+		res = PS3AV_CMD_AV_VID_480I;
+		break;
+	case PS3AV_CMD_VIDEO_VID_480P:
+		res = PS3AV_CMD_AV_VID_480P;
+		break;
+	case PS3AV_CMD_VIDEO_VID_576I:
+		res = PS3AV_CMD_AV_VID_576I;
+		break;
+	case PS3AV_CMD_VIDEO_VID_576P:
+		res = PS3AV_CMD_AV_VID_576P;
+		break;
+	case PS3AV_CMD_VIDEO_VID_1080I_60HZ:
+		res = PS3AV_CMD_AV_VID_1080I_60HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_720P_60HZ:
+		res = PS3AV_CMD_AV_VID_720P_60HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_1080P_60HZ:
+		res = PS3AV_CMD_AV_VID_1080P_60HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_1080I_50HZ:
+		res = PS3AV_CMD_AV_VID_1080I_50HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_720P_50HZ:
+		res = PS3AV_CMD_AV_VID_720P_50HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_1080P_50HZ:
+		res = PS3AV_CMD_AV_VID_1080P_50HZ;
+		break;
+	case PS3AV_CMD_VIDEO_VID_WXGA:
+		res = PS3AV_CMD_AV_VID_WXGA;
+		break;
+	case PS3AV_CMD_VIDEO_VID_SXGA:
+		res = PS3AV_CMD_AV_VID_SXGA;
+		break;
+	case PS3AV_CMD_VIDEO_VID_WUXGA:
+		res = PS3AV_CMD_AV_VID_WUXGA;
+		break;
+	default:
+		res = PS3AV_CMD_AV_VID_480P;
+		break;
+	}
+	return res;
+}
+
+int ps3av_cmd_init(void)
+{
+	int res;
+	struct ps3av_pkt_av_init av_init;
+	struct ps3av_pkt_video_init video_init;
+	struct ps3av_pkt_audio_init audio_init;
+
+	/* video init */
+	memset(&video_init, 0, sizeof(video_init));
+
+	res = ps3av_do_pkt(PS3AV_CID_VIDEO_INIT, sizeof(video_init.send_hdr),
+			   sizeof(video_init), &video_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&video_init);
+	if (res) {
+		printk(KERN_ERR "PS3AV_CID_VIDEO_INIT: failed %x\n", res);
+		return res;
+	}
+
+	/* audio init */
+	memset(&audio_init, 0, sizeof(audio_init));
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_INIT, sizeof(audio_init.send_hdr),
+			   sizeof(audio_init), &audio_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_init);
+	if (res) {
+		printk(KERN_ERR "PS3AV_CID_AUDIO_INIT: failed %x\n", res);
+		return res;
+	}
+
+	/* av init */
+	memset(&av_init, 0, sizeof(av_init));
+	av_init.event_bit = 0;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_INIT, sizeof(av_init), sizeof(av_init),
+			   &av_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_init);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_INIT: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_fin(void)
+{
+	int res;
+	struct ps3av_pkt_av_fin av_fin;
+
+	memset(&av_fin, 0, sizeof(av_fin));
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_FIN, sizeof(av_fin.send_hdr),
+			   sizeof(av_fin), &av_fin.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_fin);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_FIN: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_video_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, send_len, res;
+	struct ps3av_pkt_av_video_mute av_video_mute;
+
+	if (num_of_port > PS3AV_MUTE_PORT_MAX)
+		return -1;
+
+	memset(&av_video_mute, 0, sizeof(av_video_mute));
+	for (i = 0; i < num_of_port; i++) {
+		av_video_mute.mute[i].avport = port[i];
+		av_video_mute.mute[i].mute = mute;
+	}
+
+	send_len = sizeof(av_video_mute.send_hdr) +
+	    sizeof(struct ps3av_av_mute) * num_of_port;
+	res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_MUTE, send_len,
+			   sizeof(av_video_mute), &av_video_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_video_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_VIDEO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_video_disable_sig(u32 port)
+{
+	int res;
+	struct ps3av_pkt_av_video_disable_sig av_video_sig;
+
+	memset(&av_video_sig, 0, sizeof(av_video_sig));
+	av_video_sig.avport = port;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_DISABLE_SIG,
+			   sizeof(av_video_sig), sizeof(av_video_sig),
+			   &av_video_sig.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_video_sig);
+	if (res)
+		printk(KERN_ERR
+		       "PS3AV_CID_AV_VIDEO_DISABLE_SIG: failed %x port:%x\n",
+		       res, port);
+
+	return res;
+}
+
+int ps3av_cmd_av_tv_mute(u32 avport, u32 mute)
+{
+	int res;
+	struct ps3av_pkt_av_tv_mute tv_mute;
+
+	memset(&tv_mute, 0, sizeof(tv_mute));
+	tv_mute.avport = avport;
+	tv_mute.mute = mute;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_TV_MUTE, sizeof(tv_mute),
+			   sizeof(tv_mute), &tv_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&tv_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_TV_MUTE: failed %x port:%x\n",
+		       res, avport);
+
+	return res;
+}
+
+int ps3av_cmd_enable_event(void)
+{
+	int res;
+	struct ps3av_pkt_av_event av_event;
+
+	memset(&av_event, 0, sizeof(av_event));
+	av_event.event_bit = PS3AV_CMD_EVENT_BIT_UNPLUGGED |
+	    PS3AV_CMD_EVENT_BIT_PLUGGED | PS3AV_CMD_EVENT_BIT_HDCP_DONE;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_ENABLE_EVENT, sizeof(av_event),
+			   sizeof(av_event), &av_event.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_event);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_ENABLE_EVENT: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_hdmi_mode(u8 mode)
+{
+	int res;
+	struct ps3av_pkt_av_hdmi_mode hdmi_mode;
+
+	memset(&hdmi_mode, 0, sizeof(hdmi_mode));
+	hdmi_mode.mode = mode;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_HDMI_MODE, sizeof(hdmi_mode),
+			   sizeof(hdmi_mode), &hdmi_mode.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&hdmi_mode);
+	if (res && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+		printk(KERN_ERR "PS3AV_CID_AV_HDMI_MODE: failed %x\n", res);
+
+	return res;
+}
+
+u8 *ps3av_cmd_set_av_video_cs(u8 *p, u32 avport, int video_vid, int cs_out,
+			      int aspect, u32 id)
+{
+	struct ps3av_pkt_av_video_cs *av_video_cs;
+
+	av_video_cs = (struct ps3av_pkt_av_video_cs *)p;
+	if (video_vid == -1)
+		video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+	if (cs_out == -1)
+		cs_out = PS3AV_CMD_VIDEO_CS_YUV444_8;
+	if (aspect == -1)
+		aspect = 0;
+
+	memset(av_video_cs, 0, sizeof(*av_video_cs));
+	ps3av_set_hdr(PS3AV_CID_AV_VIDEO_CS, sizeof(*av_video_cs),
+		      &av_video_cs->send_hdr);
+	av_video_cs->avport = avport;
+	/* should be same as video_mode.resolution */
+	av_video_cs->av_vid = ps3av_vid_video2av(video_vid);
+	av_video_cs->av_cs_out = ps3av_cs_video2av(cs_out);
+	/* should be same as video_mode.video_cs_out */
+	av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
+	av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
+	av_video_cs->aspect = aspect;
+	if (id & PS3AV_MODE_DITHER) {
+		av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
+		    | PS3AV_CMD_AV_DITHER_8BIT;
+	} else {
+		/* default off */
+		av_video_cs->dither = PS3AV_CMD_AV_DITHER_OFF;
+	}
+
+	return p + sizeof(*av_video_cs);
+}
+
+u8 *ps3av_cmd_set_video_mode(u8 *p, u32 head, int video_vid, int video_fmt,
+			     u32 id)
+{
+	struct ps3av_pkt_video_mode *video_mode;
+	u32 x, y;
+
+	video_mode = (struct ps3av_pkt_video_mode *)p;
+	if (video_vid == -1)
+		video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+	if (video_fmt == -1)
+		video_fmt = PS3AV_CMD_VIDEO_FMT_X8R8G8B8;
+
+	if (ps3av_video_mode2res(id, &x, &y))
+		return p;
+
+	/* video mode */
+	memset(video_mode, 0, sizeof(*video_mode));
+	ps3av_set_hdr(PS3AV_CID_VIDEO_MODE, sizeof(*video_mode),
+		      &video_mode->send_hdr);
+	video_mode->video_head = head;
+	if (video_vid == PS3AV_CMD_VIDEO_VID_480I
+	    && head == PS3AV_CMD_VIDEO_HEAD_B)
+		video_mode->video_vid = PS3AV_CMD_VIDEO_VID_480I_A;
+	else
+		video_mode->video_vid = video_vid;
+	video_mode->width = (u16) x;
+	video_mode->height = (u16) y;
+	video_mode->pitch = video_mode->width * 4;	/* line_length */
+	video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
+	video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
+	video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
+
+	DPRINTK("video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
+		video_vid, video_mode->width, video_mode->height,
+		video_mode->pitch, video_mode->video_out_format,
+		video_mode->video_format, video_mode->video_order);
+	return p + sizeof(*video_mode);
+}
+
+int ps3av_cmd_video_format_black(u32 head, u32 video_fmt, u32 mute)
+{
+	int res;
+	struct ps3av_pkt_video_format video_format;
+
+	memset(&video_format, 0, sizeof(video_format));
+	video_format.video_head = head;
+	if (mute != PS3AV_CMD_MUTE_OFF)
+		video_format.video_format = PS3AV_CMD_VIDEO_FORMAT_BLACK;
+	else
+		video_format.video_format =
+		    ps3av_video_fmt_table[video_fmt].format;
+	video_format.video_order = ps3av_video_fmt_table[video_fmt].order;
+
+	res = ps3av_do_pkt(PS3AV_CID_VIDEO_FORMAT, sizeof(video_format),
+			   sizeof(video_format), &video_format.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&video_format);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_VIDEO_FORMAT: failed %x\n", res);
+
+	return res;
+}
+
+
+int ps3av_cmd_av_audio_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, res;
+	struct ps3av_pkt_av_audio_mute av_audio_mute;
+
+	if (num_of_port > PS3AV_MUTE_PORT_MAX)
+		return -1;
+
+	/* audio mute */
+	memset(&av_audio_mute, 0, sizeof(av_audio_mute));
+	for (i = 0; i < num_of_port; i++) {
+		av_audio_mute.mute[i].avport = port[i];
+		av_audio_mute.mute[i].mute = mute;
+	}
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_AUDIO_MUTE,
+			   sizeof(av_audio_mute.send_hdr) +
+			   sizeof(struct ps3av_av_mute) * num_of_port,
+			   sizeof(av_audio_mute), &av_audio_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_audio_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+static u8 ps3av_cnv_mclk(u32 fs)
+{
+	u8 mclk;
+
+	switch (fs) {
+	case PS3AV_CMD_AUDIO_FS_44K:
+		mclk = PS3AV_CMD_AV_MCLK_512;
+		break;
+	case PS3AV_CMD_AUDIO_FS_48K:
+		mclk = PS3AV_CMD_AV_MCLK_512;
+		break;
+	case PS3AV_CMD_AUDIO_FS_88K:
+		mclk = PS3AV_CMD_AV_MCLK_256;
+		break;
+	case PS3AV_CMD_AUDIO_FS_96K:
+		mclk = PS3AV_CMD_AV_MCLK_256;
+		break;
+	case PS3AV_CMD_AUDIO_FS_176K:
+		mclk = PS3AV_CMD_AV_MCLK_128;
+		break;
+	case PS3AV_CMD_AUDIO_FS_192K:
+		mclk = PS3AV_CMD_AV_MCLK_128;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+		mclk = 0;
+		break;
+	}
+	return mclk;
+}
+
+static const u32 ps3av_ns_table[][5] = {
+	/*   D1,    D2,    D3,    D4,    D5 */
+	{  6272,  6272, 17836, 17836,  8918 },	/*  44K */
+	{  6144,  6144, 11648, 11648,  5824 },	/*  48K */
+	{ 12544, 12544, 35672, 35672, 17836 },	/*  88K */
+	{ 12288, 12288, 23296, 23296, 11648 },	/*  96K */
+	{ 25088, 25088, 71344, 71344, 35672 },	/* 176K */
+	{ 24576, 24576, 46592, 46592, 23296 },	/* 192K */
+};
+
+static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
+{
+	u32 av_vid, ns_val;
+	u8 *p = ns;
+	int d;
+
+	d = ns_val = 0;
+	av_vid = ps3av_vid_video2av(video_vid);
+	switch (av_vid) {
+	case PS3AV_CMD_AV_VID_480I:
+	case PS3AV_CMD_AV_VID_576I:
+		d = 0;
+		break;
+	case PS3AV_CMD_AV_VID_480P:
+	case PS3AV_CMD_AV_VID_576P:
+		d = 1;
+		break;
+	case PS3AV_CMD_AV_VID_1080I_60HZ:
+	case PS3AV_CMD_AV_VID_1080I_50HZ:
+		d = 2;
+		break;
+	case PS3AV_CMD_AV_VID_720P_60HZ:
+	case PS3AV_CMD_AV_VID_720P_50HZ:
+		d = 3;
+		break;
+	case PS3AV_CMD_AV_VID_1080P_60HZ:
+	case PS3AV_CMD_AV_VID_1080P_50HZ:
+	case PS3AV_CMD_AV_VID_WXGA:
+	case PS3AV_CMD_AV_VID_SXGA:
+	case PS3AV_CMD_AV_VID_WUXGA:
+		d = 4;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, vid:%x\n", __FUNCTION__,
+		       video_vid);
+		break;
+	}
+
+	switch (fs) {
+	case PS3AV_CMD_AUDIO_FS_44K:
+		ns_val = ps3av_ns_table[0][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_48K:
+		ns_val = ps3av_ns_table[1][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_88K:
+		ns_val = ps3av_ns_table[2][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_96K:
+		ns_val = ps3av_ns_table[3][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_176K:
+		ns_val = ps3av_ns_table[4][d];
+		break;
+	case PS3AV_CMD_AUDIO_FS_192K:
+		ns_val = ps3av_ns_table[5][d];
+		break;
+	default:
+		printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+		break;
+	}
+	*p++ = ns_val & 0x000000FF;
+	*p++ = (ns_val & 0x0000FF00) >> 8;
+	*p = (ns_val & 0x00FF0000) >> 16;
+}
+
+static u8 ps3av_cnv_enable(u32 source, u8 *enable)
+{
+	u8 *p, ret = 0;
+
+	if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) {
+		ret = 0x03;
+	} else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) {
+		p = enable;
+		ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) |
+		      0x01;
+	} else
+		printk(KERN_ERR "%s failed, source:%x\n", __FUNCTION__,
+		       source);
+	return ret;
+}
+
+static u8 ps3av_cnv_fifomap(u8 *map)
+{
+	u8 *p, ret = 0;
+
+	p = map;
+	ret = p[0] + (p[1] << 2) + (p[2] << 4) + (p[3] << 6);
+	return ret;
+}
+
+static u8 ps3av_cnv_inputlen(u32 word_bits)
+{
+	u8 ret = 0;
+
+	switch (word_bits) {
+	case PS3AV_CMD_AUDIO_WORD_BITS_16:
+		ret = PS3AV_CMD_AV_INPUTLEN_16;
+		break;
+	case PS3AV_CMD_AUDIO_WORD_BITS_20:
+		ret = PS3AV_CMD_AV_INPUTLEN_20;
+		break;
+	case PS3AV_CMD_AUDIO_WORD_BITS_24:
+		ret = PS3AV_CMD_AV_INPUTLEN_24;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, word_bits:%x\n", __FUNCTION__,
+		       word_bits);
+		break;
+	}
+	return ret;
+}
+
+static u8 ps3av_cnv_layout(u32 num_of_ch)
+{
+	if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) {
+		printk(KERN_ERR "%s failed, num_of_ch:%x\n", __FUNCTION__,
+		       num_of_ch);
+		return 0;
+	}
+
+	return num_of_ch == PS3AV_CMD_AUDIO_NUM_OF_CH_2 ? 0x0 : 0x1;
+}
+
+static void ps3av_cnv_info(struct ps3av_audio_info_frame *info,
+			   const struct ps3av_pkt_audio_mode *mode)
+{
+	info->pb1.cc = mode->audio_num_of_ch + 1;	/* CH2:0x01 --- CH8:0x07 */
+	info->pb1.ct = 0;
+	info->pb2.sf = 0;
+	info->pb2.ss = 0;
+
+	info->pb3 = 0;		/* check mode->audio_format ?? */
+	info->pb4 = mode->audio_layout;
+	info->pb5.dm = mode->audio_downmix;
+	info->pb5.lsv = mode->audio_downmix_level;
+}
+
+static void ps3av_cnv_chstat(u8 *chstat, u8 *cs_info)
+{
+	memcpy(chstat, cs_info, 5);
+}
+
+u8 *ps3av_cmd_set_av_audio_param(u8 *p, u32 port,
+				 const struct ps3av_pkt_audio_mode *audio_mode,
+				 u32 video_vid)
+{
+	struct ps3av_pkt_av_audio_param *param;
+
+	param = (struct ps3av_pkt_av_audio_param *)p;
+
+	memset(param, 0, sizeof(*param));
+	ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM, sizeof(*param),
+		      &param->send_hdr);
+
+	param->avport = port;
+	param->mclk = ps3av_cnv_mclk(audio_mode->audio_fs) | 0x80;
+	ps3av_cnv_ns(param->ns, audio_mode->audio_fs, video_vid);
+	param->enable = ps3av_cnv_enable(audio_mode->audio_source,
+					 audio_mode->audio_enable);
+	param->swaplr = 0x09;
+	param->fifomap = ps3av_cnv_fifomap(audio_mode->audio_map);
+	param->inputctrl = 0x49;
+	param->inputlen = ps3av_cnv_inputlen(audio_mode->audio_word_bits);
+	param->layout = ps3av_cnv_layout(audio_mode->audio_num_of_ch);
+	ps3av_cnv_info(&param->info, audio_mode);
+	ps3av_cnv_chstat(param->chstat, audio_mode->audio_cs_info);
+
+	return p + sizeof(*param);
+}
+
+/* default cs val */
+static const u8 ps3av_mode_cs_info[] = {
+	0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
+};
+
+#define CS_44	0x00
+#define CS_48	0x02
+#define CS_88	0x08
+#define CS_96	0x0a
+#define CS_176	0x0c
+#define CS_192	0x0e
+#define CS_MASK	0x0f
+#define CS_BIT	0x40
+
+void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
+			      u32 ch, u32 fs, u32 word_bits, u32 format,
+			      u32 source)
+{
+	int spdif_through, spdif_bitstream;
+	int i;
+
+	if (!(ch | fs | format | word_bits | source)) {
+		ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2;
+		fs = PS3AV_CMD_AUDIO_FS_48K;
+		word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
+		format = PS3AV_CMD_AUDIO_FORMAT_PCM;
+		source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
+	}
+	spdif_through = spdif_bitstream = 0;	/* XXX not supported */
+
+	/* audio mode */
+	memset(audio, 0, sizeof(*audio));
+	ps3av_set_hdr(PS3AV_CID_AUDIO_MODE, sizeof(*audio), &audio->send_hdr);
+
+	audio->avport = (u8) avport;
+	audio->mask = 0x0FFF;	/* XXX set all */
+	audio->audio_num_of_ch = ch;
+	audio->audio_fs = fs;
+	audio->audio_word_bits = word_bits;
+	audio->audio_format = format;
+	audio->audio_source = source;
+
+	switch (ch) {
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
+		audio->audio_enable[3] = 1;
+		/* fall through */
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
+		audio->audio_enable[2] = 1;
+		audio->audio_enable[1] = 1;
+		/* fall through */
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
+	default:
+		audio->audio_enable[0] = 1;
+	}
+
+	/* audio swap L/R */
+	for (i = 0; i < 4; i++)
+		audio->audio_swap[i] = PS3AV_CMD_AUDIO_SWAP_0;	/* no swap */
+
+	/* audio serial input mapping */
+	audio->audio_map[0] = PS3AV_CMD_AUDIO_MAP_OUTPUT_0;
+	audio->audio_map[1] = PS3AV_CMD_AUDIO_MAP_OUTPUT_1;
+	audio->audio_map[2] = PS3AV_CMD_AUDIO_MAP_OUTPUT_2;
+	audio->audio_map[3] = PS3AV_CMD_AUDIO_MAP_OUTPUT_3;
+
+	/* audio speaker layout */
+	if (avport == PS3AV_CMD_AVPORT_HDMI_0 ||
+	    avport == PS3AV_CMD_AVPORT_HDMI_1) {
+		switch (ch) {
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_8CH;
+			break;
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_6CH;
+			break;
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
+		default:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
+			break;
+		}
+	} else {
+		audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
+	}
+
+	/* audio downmix permission */
+	audio->audio_downmix = PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED;
+	/* audio downmix level shift (0:0dB to 15:15dB) */
+	audio->audio_downmix_level = 0;	/* 0dB */
+
+	/* set ch status */
+	for (i = 0; i < 8; i++)
+		audio->audio_cs_info[i] = ps3av_mode_cs_info[i];
+
+	switch (fs) {
+	case PS3AV_CMD_AUDIO_FS_44K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_44;
+		break;
+	case PS3AV_CMD_AUDIO_FS_88K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_88;
+		break;
+	case PS3AV_CMD_AUDIO_FS_96K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_96;
+		break;
+	case PS3AV_CMD_AUDIO_FS_176K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_176;
+		break;
+	case PS3AV_CMD_AUDIO_FS_192K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_192;
+		break;
+	default:
+		break;
+	}
+
+	/* pass through setting */
+	if (spdif_through &&
+	    (avport == PS3AV_CMD_AVPORT_SPDIF_0 ||
+	     avport == PS3AV_CMD_AVPORT_SPDIF_1)) {
+		audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
+		audio->audio_source = PS3AV_CMD_AUDIO_SOURCE_SPDIF;
+		if (spdif_bitstream) {
+			audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
+			audio->audio_cs_info[0] |= CS_BIT;
+		}
+	}
+}
+
+int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *audio_mode)
+{
+	int res;
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MODE, sizeof(*audio_mode),
+			   sizeof(*audio_mode), &audio_mode->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(audio_mode);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_MODE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_audio_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, res;
+	struct ps3av_pkt_audio_mute audio_mute;
+
+	if (num_of_port > PS3AV_OPT_PORT_MAX)
+		return -1;
+
+	/* audio mute */
+	memset(&audio_mute, 0, sizeof(audio_mute));
+	for (i = 0; i < num_of_port; i++) {
+		audio_mute.mute[i].avport = port[i];
+		audio_mute.mute[i].mute = mute;
+	}
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MUTE,
+			   sizeof(audio_mute.send_hdr) +
+			   sizeof(struct ps3av_audio_mute) * num_of_port,
+			   sizeof(audio_mute), &audio_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_audio_active(int active, u32 port)
+{
+	int res;
+	struct ps3av_pkt_audio_active audio_active;
+	u32 cid;
+
+	/* audio active */
+	memset(&audio_active, 0, sizeof(audio_active));
+	audio_active.audio_port = port;
+	cid = active ? PS3AV_CID_AUDIO_ACTIVE : PS3AV_CID_AUDIO_INACTIVE;
+
+	res = ps3av_do_pkt(cid, sizeof(audio_active), sizeof(audio_active),
+			   &audio_active.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_active);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid,
+		       res);
+
+	return res;
+}
+
+int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
+{
+	int res;
+
+	/* avb packet */
+
+	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
+			   &avb->send_hdr);
+	if (res < 0)
+		goto out;
+
+	res = get_status(avb);
+	if (res)
+		DPRINTK("PS3AV_CID_AVB_PARAM: failed %x\n", res);
+
+      out:
+	return res;
+}
+
+int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *hw_conf)
+{
+	int res;
+
+	memset(hw_conf, 0, sizeof(*hw_conf));
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF, sizeof(hw_conf->send_hdr),
+			   sizeof(*hw_conf), &hw_conf->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(hw_conf);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info,
+				     u32 avport)
+{
+	int res;
+
+	memset(info, 0, sizeof(*info));
+	info->avport = avport;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_GET_MONITOR_INFO,
+			   sizeof(info->send_hdr) + sizeof(info->avport) +
+			   sizeof(info->reserved),
+			   sizeof(*info), &info->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(info);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n",
+		       res);
+
+	return res;
+}
+
+#ifdef PS3AV_DEBUG
+int ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf)
+{
+	printk("av_h_conf:num of hdmi:%d\n", hw_conf->num_of_hdmi);
+	printk("av_h_conf:num of avmulti:%d\n", hw_conf->num_of_avmulti);
+	printk("av_h_conf:num of spdif:%d\n", hw_conf->num_of_spdif);
+	return 0;
+}
+
+int ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info)
+{
+	const struct ps3av_info_monitor *info = &monitor_info->info;
+	const struct ps3av_info_audio *audio = info->audio;
+	int i;
+
+	printk("Monitor Info: size%d\n", monitor_info->send_hdr.size);
+
+	printk("avport:%02x\n", info->avport);
+	printk("monitor_id:");
+	for (i = 0; i < 10; i++)
+		printk("%02x ", info->monitor_id[i]);
+	printk("\nmonitor_type:%02x\n", info->monitor_type);
+	printk("monitor_name:");
+	for (i = 0; i < 16; i++)
+		printk("%c", info->monitor_name[i]);
+
+	/* resolution */
+	printk("\nresolution_60: bits:%08x native:%08x\n",
+	       info->res_60.res_bits, info->res_60.native);
+	printk("resolution_50: bits:%08x native:%08x\n",
+	       info->res_50.res_bits, info->res_50.native);
+	printk("resolution_other: bits:%08x native:%08x\n",
+	       info->res_other.res_bits, info->res_other.native);
+	printk("resolution_vesa: bits:%08x native:%08x\n",
+	       info->res_vesa.res_bits, info->res_vesa.native);
+
+	/* color space */
+	printk("color space    rgb:%02x\n", info->cs.rgb);
+	printk("color space yuv444:%02x\n", info->cs.yuv444);
+	printk("color space yuv422:%02x\n", info->cs.yuv422);
+
+	/* color info */
+	printk("color info   red:X %04x Y %04x\n",
+	       info->color.red_x, info->color.red_y);
+	printk("color info green:X %04x Y %04x\n",
+	       info->color.green_x, info->color.green_y);
+	printk("color info  blue:X %04x Y %04x\n",
+	       info->color.blue_x, info->color.blue_y);
+	printk("color info white:X %04x Y %04x\n",
+	       info->color.white_x, info->color.white_y);
+	printk("color info gamma: %08x\n", info->color.gamma);
+
+	/* other info */
+	printk("supported_AI:%02x\n", info->supported_ai);
+	printk("speaker_info:%02x\n", info->speaker_info);
+	printk("num of audio:%02x\n", info->num_of_audio_block);
+
+	/* audio block */
+	for (i = 0; i < info->num_of_audio_block; i++) {
+		printk("audio[%d] type:%02x max_ch:%02x fs:%02x sbit:%02x\n",
+		       i, audio->type, audio->max_num_of_ch, audio->fs,
+		       audio->sbit);
+		audio++;
+	}
+
+	return 0;
+}
+#endif /* PS3AV_DEBUG */
+
+#define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \
+		| PS3AV_CMD_AV_LAYOUT_44 \
+		| PS3AV_CMD_AV_LAYOUT_48)
+
+#define PS3AV_AV_LAYOUT_1 (PS3AV_AV_LAYOUT_0 \
+		| PS3AV_CMD_AV_LAYOUT_88 \
+		| PS3AV_CMD_AV_LAYOUT_96 \
+		| PS3AV_CMD_AV_LAYOUT_176 \
+		| PS3AV_CMD_AV_LAYOUT_192)
+
+/************************* vuart ***************************/
+
+#define POLLING_INTERVAL  25	/* in msec */
+
+int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
+		      unsigned long size)
+{
+	int error = ps3_vuart_write(dev, buf, size);
+	return error ? error : size;
+}
+
+int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
+		     unsigned long size, int timeout)
+{
+	int error;
+	int loopcnt = 0;
+
+	timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
+	while (loopcnt++ <= timeout) {
+		error = ps3_vuart_read(dev, buf, size);
+		if (!error)
+			return size;
+		if (error != -EAGAIN) {
+			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
+			       __FUNCTION__, error);
+			return error;
+		}
+		msleep(POLLING_INTERVAL);
+	}
+	return -EWOULDBLOCK;
+}
--- /dev/null
+++ ps3-linux/include/asm-powerpc/ps3av.h
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef _PS3AV_H_
+#define _PS3AV_H_
+
+/** command for ioctl() **/
+#define PS3AV_VERSION 0x205	/* version of ps3av command */
+
+#define PS3AV_CID_AV_INIT              0x00000001
+#define PS3AV_CID_AV_FIN               0x00000002
+#define PS3AV_CID_AV_GET_HW_CONF       0x00000003
+#define PS3AV_CID_AV_GET_MONITOR_INFO  0x00000004
+#define PS3AV_CID_AV_ENABLE_EVENT      0x00000006
+#define PS3AV_CID_AV_DISABLE_EVENT     0x00000007
+#define PS3AV_CID_AV_TV_MUTE           0x0000000a
+
+#define PS3AV_CID_AV_VIDEO_CS          0x00010001
+#define PS3AV_CID_AV_VIDEO_MUTE        0x00010002
+#define PS3AV_CID_AV_VIDEO_DISABLE_SIG 0x00010003
+#define PS3AV_CID_AV_AUDIO_PARAM       0x00020001
+#define PS3AV_CID_AV_AUDIO_MUTE        0x00020002
+#define PS3AV_CID_AV_HDMI_MODE         0x00040001
+
+#define PS3AV_CID_VIDEO_INIT           0x01000001
+#define PS3AV_CID_VIDEO_MODE           0x01000002
+#define PS3AV_CID_VIDEO_FORMAT         0x01000004
+#define PS3AV_CID_VIDEO_PITCH          0x01000005
+
+#define PS3AV_CID_AUDIO_INIT           0x02000001
+#define PS3AV_CID_AUDIO_MODE           0x02000002
+#define PS3AV_CID_AUDIO_MUTE           0x02000003
+#define PS3AV_CID_AUDIO_ACTIVE         0x02000004
+#define PS3AV_CID_AUDIO_INACTIVE       0x02000005
+#define PS3AV_CID_AUDIO_SPDIF_BIT      0x02000006
+#define PS3AV_CID_AUDIO_CTRL           0x02000007
+
+#define PS3AV_CID_EVENT_UNPLUGGED      0x10000001
+#define PS3AV_CID_EVENT_PLUGGED        0x10000002
+#define PS3AV_CID_EVENT_HDCP_DONE      0x10000003
+#define PS3AV_CID_EVENT_HDCP_FAIL      0x10000004
+#define PS3AV_CID_EVENT_HDCP_AUTH      0x10000005
+#define PS3AV_CID_EVENT_HDCP_ERROR     0x10000006
+
+#define PS3AV_CID_AVB_PARAM            0x04000001
+
+/* max backend ports */
+#define PS3AV_HDMI_MAX                 2	/* HDMI_0 HDMI_1 */
+#define PS3AV_AVMULTI_MAX              1	/* AVMULTI_0 */
+#define PS3AV_AV_PORT_MAX              (PS3AV_HDMI_MAX + PS3AV_AVMULTI_MAX)
+#define PS3AV_OPT_PORT_MAX             1	/* SPDIF0 */
+#define PS3AV_HEAD_MAX                 2	/* HEAD_A HEAD_B */
+
+/* num of pkt for PS3AV_CID_AVB_PARAM */
+#define PS3AV_AVB_NUM_VIDEO            PS3AV_HEAD_MAX
+#define PS3AV_AVB_NUM_AUDIO            0	/* not supported */
+#define PS3AV_AVB_NUM_AV_VIDEO         PS3AV_AV_PORT_MAX
+#define PS3AV_AVB_NUM_AV_AUDIO         PS3AV_HDMI_MAX
+
+#define PS3AV_MUTE_PORT_MAX            1	/* num of ports in mute pkt */
+
+/* event_bit */
+#define PS3AV_CMD_EVENT_BIT_UNPLUGGED			(1 << 0)
+#define PS3AV_CMD_EVENT_BIT_PLUGGED			(1 << 1)
+#define PS3AV_CMD_EVENT_BIT_HDCP_DONE			(1 << 2)
+#define PS3AV_CMD_EVENT_BIT_HDCP_FAIL			(1 << 3)
+#define PS3AV_CMD_EVENT_BIT_HDCP_REAUTH			(1 << 4)
+#define PS3AV_CMD_EVENT_BIT_HDCP_TOPOLOGY		(1 << 5)
+
+/* common params */
+/* mute */
+#define PS3AV_CMD_MUTE_OFF				0x0000
+#define PS3AV_CMD_MUTE_ON				0x0001
+/* avport */
+#define PS3AV_CMD_AVPORT_HDMI_0				0x0000
+#define PS3AV_CMD_AVPORT_HDMI_1				0x0001
+#define PS3AV_CMD_AVPORT_AVMULTI_0			0x0010
+#define PS3AV_CMD_AVPORT_SPDIF_0			0x0020
+#define PS3AV_CMD_AVPORT_SPDIF_1			0x0021
+
+/* for av backend */
+/* av_mclk */
+#define PS3AV_CMD_AV_MCLK_128				0x0000
+#define PS3AV_CMD_AV_MCLK_256				0x0001
+#define PS3AV_CMD_AV_MCLK_512				0x0003
+/* av_inputlen */
+#define PS3AV_CMD_AV_INPUTLEN_16			0x02
+#define PS3AV_CMD_AV_INPUTLEN_20			0x0a
+#define PS3AV_CMD_AV_INPUTLEN_24			0x0b
+/* alayout */
+#define PS3AV_CMD_AV_LAYOUT_32				(1 << 0)
+#define PS3AV_CMD_AV_LAYOUT_44				(1 << 1)
+#define PS3AV_CMD_AV_LAYOUT_48				(1 << 2)
+#define PS3AV_CMD_AV_LAYOUT_88				(1 << 3)
+#define PS3AV_CMD_AV_LAYOUT_96				(1 << 4)
+#define PS3AV_CMD_AV_LAYOUT_176				(1 << 5)
+#define PS3AV_CMD_AV_LAYOUT_192				(1 << 6)
+/* hdmi_mode */
+#define PS3AV_CMD_AV_HDMI_MODE_NORMAL			0xff
+#define PS3AV_CMD_AV_HDMI_HDCP_OFF			0x01
+#define PS3AV_CMD_AV_HDMI_EDID_PASS			0x80
+#define PS3AV_CMD_AV_HDMI_DVI				0x40
+
+/* for video module */
+/* video_head */
+#define PS3AV_CMD_VIDEO_HEAD_A				0x0000
+#define PS3AV_CMD_VIDEO_HEAD_B				0x0001
+/* video_cs_out video_cs_in */
+#define PS3AV_CMD_VIDEO_CS_NONE				0x0000
+#define PS3AV_CMD_VIDEO_CS_RGB_8			0x0001
+#define PS3AV_CMD_VIDEO_CS_YUV444_8			0x0002
+#define PS3AV_CMD_VIDEO_CS_YUV422_8			0x0003
+#define PS3AV_CMD_VIDEO_CS_XVYCC_8			0x0004
+#define PS3AV_CMD_VIDEO_CS_RGB_10			0x0005
+#define PS3AV_CMD_VIDEO_CS_YUV444_10			0x0006
+#define PS3AV_CMD_VIDEO_CS_YUV422_10			0x0007
+#define PS3AV_CMD_VIDEO_CS_XVYCC_10			0x0008
+#define PS3AV_CMD_VIDEO_CS_RGB_12			0x0009
+#define PS3AV_CMD_VIDEO_CS_YUV444_12			0x000a
+#define PS3AV_CMD_VIDEO_CS_YUV422_12			0x000b
+#define PS3AV_CMD_VIDEO_CS_XVYCC_12			0x000c
+/* video_vid */
+#define PS3AV_CMD_VIDEO_VID_NONE			0x0000
+#define PS3AV_CMD_VIDEO_VID_480I			0x0001
+#define PS3AV_CMD_VIDEO_VID_576I			0x0003
+#define PS3AV_CMD_VIDEO_VID_480P			0x0005
+#define PS3AV_CMD_VIDEO_VID_576P			0x0006
+#define PS3AV_CMD_VIDEO_VID_1080I_60HZ			0x0007
+#define PS3AV_CMD_VIDEO_VID_1080I_50HZ			0x0008
+#define PS3AV_CMD_VIDEO_VID_720P_60HZ			0x0009
+#define PS3AV_CMD_VIDEO_VID_720P_50HZ			0x000a
+#define PS3AV_CMD_VIDEO_VID_1080P_60HZ			0x000b
+#define PS3AV_CMD_VIDEO_VID_1080P_50HZ			0x000c
+#define PS3AV_CMD_VIDEO_VID_WXGA			0x000d
+#define PS3AV_CMD_VIDEO_VID_SXGA			0x000e
+#define PS3AV_CMD_VIDEO_VID_WUXGA			0x000f
+#define PS3AV_CMD_VIDEO_VID_480I_A			0x0010
+/* video_format */
+#define PS3AV_CMD_VIDEO_FORMAT_BLACK			0x0000
+#define PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT		0x0007
+/* video_order */
+#define PS3AV_CMD_VIDEO_ORDER_RGB			0x0000
+#define PS3AV_CMD_VIDEO_ORDER_BGR			0x0001
+/* video_fmt */
+#define PS3AV_CMD_VIDEO_FMT_X8R8G8B8			0x0000
+/* video_out_format */
+#define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT		0x0000
+/* video_sync */
+#define PS3AV_CMD_VIDEO_SYNC_VSYNC			0x0001
+#define PS3AV_CMD_VIDEO_SYNC_CSYNC			0x0004
+#define PS3AV_CMD_VIDEO_SYNC_HSYNC			0x0010
+
+/* for audio module */
+/* num_of_ch */
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_2			0x0000
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_3			0x0001
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_4			0x0002
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_5			0x0003
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_6			0x0004
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_7			0x0005
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_8			0x0006
+/* audio_fs */
+#define PS3AV_CMD_AUDIO_FS_32K				0x0001
+#define PS3AV_CMD_AUDIO_FS_44K				0x0002
+#define PS3AV_CMD_AUDIO_FS_48K				0x0003
+#define PS3AV_CMD_AUDIO_FS_88K				0x0004
+#define PS3AV_CMD_AUDIO_FS_96K				0x0005
+#define PS3AV_CMD_AUDIO_FS_176K				0x0006
+#define PS3AV_CMD_AUDIO_FS_192K				0x0007
+/* audio_word_bits */
+#define PS3AV_CMD_AUDIO_WORD_BITS_16			0x0001
+#define PS3AV_CMD_AUDIO_WORD_BITS_20			0x0002
+#define PS3AV_CMD_AUDIO_WORD_BITS_24			0x0003
+/* audio_format */
+#define PS3AV_CMD_AUDIO_FORMAT_PCM			0x0001
+#define PS3AV_CMD_AUDIO_FORMAT_BITSTREAM		0x00ff
+/* audio_source */
+#define PS3AV_CMD_AUDIO_SOURCE_SERIAL			0x0000
+#define PS3AV_CMD_AUDIO_SOURCE_SPDIF			0x0001
+/* audio_swap */
+#define PS3AV_CMD_AUDIO_SWAP_0				0x0000
+#define PS3AV_CMD_AUDIO_SWAP_1				0x0000
+/* audio_map */
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_0			0x0000
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_1			0x0001
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_2			0x0002
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_3			0x0003
+/* audio_layout */
+#define PS3AV_CMD_AUDIO_LAYOUT_2CH			0x0000
+#define PS3AV_CMD_AUDIO_LAYOUT_6CH			0x000b	/* LREClr */
+#define PS3AV_CMD_AUDIO_LAYOUT_8CH			0x001f	/* LREClrXY */
+/* audio_downmix */
+#define PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED		0x0000
+#define PS3AV_CMD_AUDIO_DOWNMIX_PROHIBITED		0x0001
+
+/* audio_port */
+#define PS3AV_CMD_AUDIO_PORT_HDMI_0			( 1 << 0 )
+#define PS3AV_CMD_AUDIO_PORT_HDMI_1			( 1 << 1 )
+#define PS3AV_CMD_AUDIO_PORT_AVMULTI_0			( 1 << 10 )
+#define PS3AV_CMD_AUDIO_PORT_SPDIF_0			( 1 << 20 )
+#define PS3AV_CMD_AUDIO_PORT_SPDIF_1			( 1 << 21 )
+
+/* audio_ctrl_id */
+#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_RESET		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_DE_EMPHASIS		0x0001
+#define PS3AV_CMD_AUDIO_CTRL_ID_AVCLK			0x0002
+/* audio_ctrl_data[0] reset */
+#define PS3AV_CMD_AUDIO_CTRL_RESET_NEGATE		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_RESET_ASSERT		0x0001
+/* audio_ctrl_data[0] de-emphasis */
+#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_OFF		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_ON		0x0001
+/* audio_ctrl_data[0] avclk */
+#define PS3AV_CMD_AUDIO_CTRL_AVCLK_22			0x0000
+#define PS3AV_CMD_AUDIO_CTRL_AVCLK_18			0x0001
+
+/* av_vid */
+/* do not use these params directly, use vid_video2av */
+#define PS3AV_CMD_AV_VID_480I				0x0000
+#define PS3AV_CMD_AV_VID_480P				0x0001
+#define PS3AV_CMD_AV_VID_720P_60HZ			0x0002
+#define PS3AV_CMD_AV_VID_1080I_60HZ			0x0003
+#define PS3AV_CMD_AV_VID_1080P_60HZ			0x0004
+#define PS3AV_CMD_AV_VID_576I				0x0005
+#define PS3AV_CMD_AV_VID_576P				0x0006
+#define PS3AV_CMD_AV_VID_720P_50HZ			0x0007
+#define PS3AV_CMD_AV_VID_1080I_50HZ			0x0008
+#define PS3AV_CMD_AV_VID_1080P_50HZ			0x0009
+#define PS3AV_CMD_AV_VID_WXGA				0x000a
+#define PS3AV_CMD_AV_VID_SXGA				0x000b
+#define PS3AV_CMD_AV_VID_WUXGA				0x000c
+/* av_cs_out av_cs_in */
+/* use cs_video2av() */
+#define PS3AV_CMD_AV_CS_RGB_8				0x0000
+#define PS3AV_CMD_AV_CS_YUV444_8			0x0001
+#define PS3AV_CMD_AV_CS_YUV422_8			0x0002
+#define PS3AV_CMD_AV_CS_XVYCC_8				0x0003
+#define PS3AV_CMD_AV_CS_RGB_10				0x0004
+#define PS3AV_CMD_AV_CS_YUV444_10			0x0005
+#define PS3AV_CMD_AV_CS_YUV422_10			0x0006
+#define PS3AV_CMD_AV_CS_XVYCC_10			0x0007
+#define PS3AV_CMD_AV_CS_RGB_12				0x0008
+#define PS3AV_CMD_AV_CS_YUV444_12			0x0009
+#define PS3AV_CMD_AV_CS_YUV422_12			0x000a
+#define PS3AV_CMD_AV_CS_XVYCC_12			0x000b
+#define PS3AV_CMD_AV_CS_8				0x0000
+#define PS3AV_CMD_AV_CS_10				0x0001
+#define PS3AV_CMD_AV_CS_12				0x0002
+/* dither */
+#define PS3AV_CMD_AV_DITHER_OFF				0x0000
+#define PS3AV_CMD_AV_DITHER_ON				0x0001
+#define PS3AV_CMD_AV_DITHER_8BIT			0x0000
+#define PS3AV_CMD_AV_DITHER_10BIT			0x0002
+#define PS3AV_CMD_AV_DITHER_12BIT			0x0004
+/* super_white */
+#define PS3AV_CMD_AV_SUPER_WHITE_OFF			0x0000
+#define PS3AV_CMD_AV_SUPER_WHITE_ON			0x0001
+/* aspect */
+#define PS3AV_CMD_AV_ASPECT_16_9			0x0000
+#define PS3AV_CMD_AV_ASPECT_4_3				0x0001
+/* video_cs_cnv() */
+#define PS3AV_CMD_VIDEO_CS_RGB				0x0001
+#define PS3AV_CMD_VIDEO_CS_YUV422			0x0002
+#define PS3AV_CMD_VIDEO_CS_YUV444			0x0003
+
+/* for automode */
+#define PS3AV_RESBIT_720x480P			0x0003	/* 0x0001 | 0x0002 */
+#define PS3AV_RESBIT_720x576P			0x0003	/* 0x0001 | 0x0002 */
+#define PS3AV_RESBIT_1280x720P			0x0004
+#define PS3AV_RESBIT_1920x1080I			0x0008
+#define PS3AV_RESBIT_1920x1080P			0x4000
+#define PS3AV_RES_MASK_60			(PS3AV_RESBIT_720x480P \
+						| PS3AV_RESBIT_1280x720P \
+						| PS3AV_RESBIT_1920x1080I \
+						| PS3AV_RESBIT_1920x1080P)
+#define PS3AV_RES_MASK_50			(PS3AV_RESBIT_720x576P \
+						| PS3AV_RESBIT_1280x720P \
+						| PS3AV_RESBIT_1920x1080I \
+						| PS3AV_RESBIT_1920x1080P)
+
+#define PS3AV_MONITOR_TYPE_HDMI			1	/* HDMI */
+#define PS3AV_MONITOR_TYPE_DVI			2	/* DVI */
+#define PS3AV_DEFAULT_HDMI_VID_REG_60		PS3AV_CMD_VIDEO_VID_480P
+#define PS3AV_DEFAULT_AVMULTI_VID_REG_60	PS3AV_CMD_VIDEO_VID_480I
+#define PS3AV_DEFAULT_HDMI_VID_REG_50		PS3AV_CMD_VIDEO_VID_576P
+#define PS3AV_DEFAULT_AVMULTI_VID_REG_50	PS3AV_CMD_VIDEO_VID_576I
+#define PS3AV_DEFAULT_DVI_VID			PS3AV_CMD_VIDEO_VID_480P
+
+#define PS3AV_REGION_60				0x01
+#define PS3AV_REGION_50				0x02
+#define PS3AV_REGION_RGB			0x10
+
+#define get_status(buf)				(((__u32 *)buf)[2])
+#define PS3AV_HDR_SIZE				4	/* version + size */
+
+/* for video mode */
+#define PS3AV_MODE_MASK				0x000F
+#define PS3AV_MODE_HDCP_OFF			0x1000	/* Retail PS3 product doesn't support this */
+#define PS3AV_MODE_DITHER			0x0800
+#define PS3AV_MODE_FULL				0x0080
+#define PS3AV_MODE_DVI				0x0040
+#define PS3AV_MODE_RGB				0x0020
+
+#ifdef __KERNEL__
+/** command packet structure **/
+struct ps3av_send_hdr {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+};
+
+struct ps3av_reply_hdr {
+	u16 version;
+	u16 size;
+	u32 cid;
+	u32 status;
+};
+
+/* backend: initialization */
+struct ps3av_pkt_av_init {
+	struct ps3av_send_hdr send_hdr;
+	u32 event_bit;
+};
+
+/* backend: finalize */
+struct ps3av_pkt_av_fin {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* backend: get port */
+struct ps3av_pkt_av_get_hw_conf {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 status;
+	u16 num_of_hdmi;	/* out: number of hdmi */
+	u16 num_of_avmulti;	/* out: number of avmulti */
+	u16 num_of_spdif;	/* out: number of hdmi */
+	u16 reserved;
+};
+
+/* backend: get monitor info */
+struct ps3av_info_resolution {
+	u32 res_bits;
+	u32 native;
+};
+
+struct ps3av_info_cs {
+	u8 rgb;
+	u8 yuv444;
+	u8 yuv422;
+	u8 reserved;
+};
+
+struct ps3av_info_color {
+	u16 red_x;
+	u16 red_y;
+	u16 green_x;
+	u16 green_y;
+	u16 blue_x;
+	u16 blue_y;
+	u16 white_x;
+	u16 white_y;
+	u32 gamma;
+};
+
+struct ps3av_info_audio {
+	u8 type;
+	u8 max_num_of_ch;
+	u8 fs;
+	u8 sbit;
+};
+
+struct ps3av_info_monitor {
+	u8 avport;
+	u8 monitor_id[10];
+	u8 monitor_type;
+	u8 monitor_name[16];
+	struct ps3av_info_resolution res_60;
+	struct ps3av_info_resolution res_50;
+	struct ps3av_info_resolution res_other;
+	struct ps3av_info_resolution res_vesa;
+	struct ps3av_info_cs cs;
+	struct ps3av_info_color color;
+	u8 supported_ai;
+	u8 speaker_info;
+	u8 num_of_audio_block;
+	struct ps3av_info_audio audio[0];	/* 0 or more audio blocks */
+	u8 reserved[169];
+} __attribute__ ((packed));
+
+struct ps3av_pkt_av_get_monitor_info {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+	/* recv */
+	struct ps3av_info_monitor info;	/* out: monitor info */
+};
+
+/* backend: enable/disable event */
+struct ps3av_pkt_av_event {
+	struct ps3av_send_hdr send_hdr;
+	u32 event_bit;		/* in */
+};
+
+/* backend: video cs param */
+struct ps3av_pkt_av_video_cs {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 av_vid;		/* in: video resolution */
+	u16 av_cs_out;		/* in: output color space */
+	u16 av_cs_in;		/* in: input color space */
+	u8 dither;		/* in: dither bit length */
+	u8 bitlen_out;		/* in: bit length */
+	u8 super_white;		/* in: super white */
+	u8 aspect;		/* in: aspect ratio */
+};
+
+/* backend: video mute */
+struct ps3av_av_mute {
+	u16 avport;		/* in: avport */
+	u16 mute;		/* in: mute on/off */
+};
+
+struct ps3av_pkt_av_video_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
+};
+
+/* backend: video disable signal */
+struct ps3av_pkt_av_video_disable_sig {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+};
+
+/* backend: audio param */
+struct ps3av_audio_info_frame {
+	struct pb1_bit {
+		u8 ct:4;
+		u8 rsv:1;
+		u8 cc:3;
+	} pb1;
+	struct pb2_bit {
+		u8 rsv:3;
+		u8 sf:3;
+		u8 ss:2;
+	} pb2;
+	u8 pb3;
+	u8 pb4;
+	struct pb5_bit {
+		u8 dm:1;
+		u8 lsv:4;
+		u8 rsv:3;
+	} pb5;
+};
+
+struct ps3av_pkt_av_audio_param {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+	u8 mclk;		/* in: audio mclk */
+	u8 ns[3];		/* in: audio ns val */
+	u8 enable;		/* in: audio enable */
+	u8 swaplr;		/* in: audio swap */
+	u8 fifomap;		/* in: audio fifomap */
+	u8 inputctrl;		/* in: audio input ctrl */
+	u8 inputlen;		/* in: sample bit size */
+	u8 layout;		/* in: speaker layout param */
+	struct ps3av_audio_info_frame info;	/* in: info */
+	u8 chstat[5];		/* in: ch stat */
+};
+
+/* backend: audio_mute */
+struct ps3av_pkt_av_audio_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
+};
+
+/* backend: hdmi_mode */
+struct ps3av_pkt_av_hdmi_mode {
+	struct ps3av_send_hdr send_hdr;
+	u8 mode;		/* in: hdmi_mode */
+	u8 reserved0;
+	u8 reserved1;
+	u8 reserved2;
+};
+
+/* backend: tv_mute */
+struct ps3av_pkt_av_tv_mute {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport HDMI only */
+	u16 mute;		/* in: mute */
+};
+
+/* video: initialize */
+struct ps3av_pkt_video_init {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* video: mode setting */
+struct ps3av_pkt_video_mode {
+	struct ps3av_send_hdr send_hdr;
+	u32 video_head;		/* in: head */
+	u32 reserved;
+	u32 video_vid;		/* in: video resolution */
+	u16 reserved1;
+	u16 width;		/* in: width in pixel */
+	u16 reserved2;
+	u16 height;		/* in: height in pixel */
+	u32 pitch;		/* in: line size in byte */
+	u32 video_out_format;	/* in: out format */
+	u32 video_format;	/* in: input frame buffer format */
+	u8 reserved3;
+	u8 reserved4;
+	u16 video_order;	/* in: input RGB order */
+	u32 reserved5;
+};
+
+/* video: format */
+struct ps3av_pkt_video_format {
+	struct ps3av_send_hdr send_hdr;
+	u32 video_head;		/* in: head */
+	u32 video_format;	/* in: frame buffer format */
+	u16 reserved;
+	u16 video_order;	/* in: input RGB order */
+};
+
+/* video: pitch */
+struct ps3av_pkt_video_pitch {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u32 video_head;		/* in: head */
+	u32 pitch;		/* in: line size in byte */
+};
+
+/* audio: initialize */
+struct ps3av_pkt_audio_init {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* audio: mode setting */
+struct ps3av_pkt_audio_mode {
+	struct ps3av_send_hdr send_hdr;
+	u8 avport;		/* in: avport */
+	u8 reserved0[3];
+	u32 mask;		/* in: mask */
+	u32 audio_num_of_ch;	/* in: number of ch */
+	u32 audio_fs;		/* in: sampling freq */
+	u32 audio_word_bits;	/* in: sample bit size */
+	u32 audio_format;	/* in: audio output format */
+	u32 audio_source;	/* in: audio source */
+	u8 audio_enable[4];	/* in: audio enable */
+	u8 audio_swap[4];	/* in: audio swap */
+	u8 audio_map[4];	/* in: audio map */
+	u32 audio_layout;	/* in: speaker layout */
+	u32 audio_downmix;	/* in: audio downmix permission */
+	u32 audio_downmix_level;
+	u8 audio_cs_info[8];	/* in: IEC channel status */
+};
+
+/* audio: mute */
+struct ps3av_audio_mute {
+	u8 avport;		/* in: opt_port optical */
+	u8 reserved[3];
+	u32 mute;		/* in: mute */
+};
+
+struct ps3av_pkt_audio_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_audio_mute mute[PS3AV_OPT_PORT_MAX];
+};
+
+/* audio: active/inactive */
+struct ps3av_pkt_audio_active {
+	struct ps3av_send_hdr send_hdr;
+	u32 audio_port;		/* in: audio active/inactive port */
+};
+
+/* audio: SPDIF user bit */
+struct ps3av_pkt_audio_spdif_bit {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u8 avport;		/* in: avport SPDIF only */
+	u8 reserved[3];
+	u32 audio_port;		/* in: SPDIF only */
+	u32 spdif_bit_data[12];	/* in: user bit data */
+};
+
+/* audio: audio control */
+struct ps3av_pkt_audio_ctrl {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u32 audio_ctrl_id;	/* in: control id */
+	u32 audio_ctrl_data[4];	/* in: control data */
+};
+
+/* avb:param */
+struct ps3av_pkt_avb_param {
+	struct ps3av_send_hdr send_hdr;
+	u16 num_of_video_pkt;
+	u16 num_of_audio_pkt;
+	u16 num_of_av_video_pkt;
+	u16 num_of_av_audio_pkt;
+	struct ps3av_pkt_video_mode video[PS3AV_AVB_NUM_VIDEO];
+	struct ps3av_pkt_audio_mode audio[PS3AV_AVB_NUM_AUDIO];
+	struct ps3av_pkt_av_video_cs av_video[PS3AV_AVB_NUM_AV_VIDEO];
+	struct ps3av_pkt_av_audio_param av_audio[PS3AV_AVB_NUM_AV_AUDIO];
+};
+
+struct ps3av {
+	int available;
+	struct semaphore sem;
+	struct ps3_vuart_port_device *dev;
+
+	int region;
+	struct ps3av_pkt_av_get_hw_conf av_hw_conf;
+	u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX];
+	u32 opt_port[PS3AV_OPT_PORT_MAX];
+	u32 head[PS3AV_HEAD_MAX];
+	u32 audio_port;
+	atomic_t ps3av_mode;
+};
+
+/** command status **/
+#define PS3AV_STATUS_SUCCESS			0x0000	/* success */
+#define PS3AV_STATUS_RECEIVE_VUART_ERROR	0x0001	/* receive vuart error */
+#define PS3AV_STATUS_SYSCON_COMMUNICATE_FAIL	0x0002	/* syscon communication error */
+#define PS3AV_STATUS_INVALID_COMMAND		0x0003	/* obsolete invalid CID */
+#define PS3AV_STATUS_INVALID_PORT		0x0004	/* invalid port number */
+#define PS3AV_STATUS_INVALID_VID		0x0005	/* invalid video format */
+#define PS3AV_STATUS_INVALID_COLOR_SPACE	0x0006	/* invalid video colose space */
+#define PS3AV_STATUS_INVALID_FS			0x0007	/* invalid audio sampling freq */
+#define PS3AV_STATUS_INVALID_AUDIO_CH		0x0008	/* invalid audio channel number */
+#define PS3AV_STATUS_UNSUPPORTED_VERSION	0x0009	/* version mismatch  */
+#define PS3AV_STATUS_INVALID_SAMPLE_SIZE	0x000a	/* invalid audio sample bit size */
+#define PS3AV_STATUS_FAILURE			0x000b	/* other failures */
+#define PS3AV_STATUS_UNSUPPORTED_COMMAND	0x000c	/* unsupported cid */
+#define PS3AV_STATUS_BUFFER_OVERFLOW		0x000d	/* write buffer overflow */
+#define PS3AV_STATUS_INVALID_VIDEO_PARAM	0x000e	/* invalid video param */
+#define PS3AV_STATUS_NO_SEL			0x000f	/* not exist selector */
+#define PS3AV_STATUS_INVALID_AV_PARAM		0x0010	/* invalid backend param */
+#define PS3AV_STATUS_INVALID_AUDIO_PARAM	0x0011	/* invalid audio param */
+#define PS3AV_STATUS_UNSUPPORTED_HDMI_MODE	0x0012	/* unsupported hdmi mode */
+#define PS3AV_STATUS_NO_SYNC_HEAD		0x0013	/* sync head failed */
+
+extern void ps3av_set_hdr(u32, u16, struct ps3av_send_hdr *);
+extern int ps3av_do_pkt(u32, u16, size_t, struct ps3av_send_hdr *);
+
+extern int ps3av_cmd_init(void);
+extern int ps3av_cmd_fin(void);
+extern int ps3av_cmd_av_video_mute(int, u32 *, u32);
+extern int ps3av_cmd_av_video_disable_sig(u32);
+extern int ps3av_cmd_av_tv_mute(u32, u32);
+extern int ps3av_cmd_enable_event(void);
+extern int ps3av_cmd_av_hdmi_mode(u8);
+extern u8 *ps3av_cmd_set_av_video_cs(u8 *, u32, int, int, int, u32);
+extern u8 *ps3av_cmd_set_video_mode(u8 *, u32, int, int, u32);
+extern int ps3av_cmd_video_format_black(u32, u32, u32);
+extern int ps3av_cmd_av_audio_mute(int, u32 *, u32);
+extern u8 *ps3av_cmd_set_av_audio_param(u8 *, u32,
+					const struct ps3av_pkt_audio_mode *,
+					u32);
+extern void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *, u32, u32,
+				     u32, u32, u32, u32);
+extern int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *);
+extern int ps3av_cmd_audio_mute(int, u32 *, u32);
+extern int ps3av_cmd_audio_active(int, u32);
+extern int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *, u32);
+extern int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *);
+extern int ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *);
+extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
+					    u32);
+extern int ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *);
+
+extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
+			     const void *buf, unsigned long size);
+extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
+			    unsigned long size, int timeout);
+
+extern int ps3av_set_video_mode(u32, int);
+extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
+extern int ps3av_set_mode(u32, int);
+extern int ps3av_get_mode(void);
+extern int ps3av_get_scanmode(int);
+extern int ps3av_get_refresh_rate(int);
+extern int ps3av_video_mode2res(u32, u32 *, u32 *);
+extern int ps3av_video_mute(int);
+extern int ps3av_audio_mute(int);
+extern int ps3av_dev_open(void);
+extern int ps3av_dev_close(void);
+#endif	/* __KERNEL__ */
+
+#endif	/* _PS3AV_H_ */

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 2/9] fbdev modedb: allow refresh rates for named video modes
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:48   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:48 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

fbdev modedb: Take into account the specified refresh rates for video modes
specified by name, so e.g. all of `720p', `720p@60', and `720p@50' work.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/video/modedb.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

--- ps3-linux.orig/drivers/video/modedb.c
+++ ps3-linux/drivers/video/modedb.c
@@ -610,10 +610,8 @@ done:
 	diff = refresh;
 	best = -1;
 	for (i = 0; i < dbsize; i++) {
-		if ((name_matches(db[i], name, namelen) &&
-			!fb_try_mode(var, info, &db[i], bpp)))
-			return 1;
-		if (res_specified && res_matches(db[i], xres, yres)) {
+		if (name_matches(db[i], name, namelen) ||
+		    (res_specified && res_matches(db[i], xres, yres))) {
 			if(!fb_try_mode(var, info, &db[i], bpp)) {
 				if(!refresh_specified || db[i].refresh == refresh)
 					return 1;
Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 2/9] fbdev modedb: allow refresh rates for named video modes
@ 2007-01-25 17:48   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:48 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

fbdev modedb: Take into account the specified refresh rates for video modes
specified by name, so e.g. all of `720p', `720p@60', and `720p@50' work.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/video/modedb.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

--- ps3-linux.orig/drivers/video/modedb.c
+++ ps3-linux/drivers/video/modedb.c
@@ -610,10 +610,8 @@ done:
 	diff = refresh;
 	best = -1;
 	for (i = 0; i < dbsize; i++) {
-		if ((name_matches(db[i], name, namelen) &&
-			!fb_try_mode(var, info, &db[i], bpp)))
-			return 1;
-		if (res_specified && res_matches(db[i], xres, yres)) {
+		if (name_matches(db[i], name, namelen) ||
+		    (res_specified && res_matches(db[i], xres, yres))) {
 			if(!fb_try_mode(var, info, &db[i], bpp)) {
 				if(!refresh_specified || db[i].refresh == refresh)
 					return 1;
Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 3/9] fbdev modedb: make more pointer parameters const
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:49   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:49 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

fbdev modedb: make more input and output pointer parameters const

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/video/console/fbcon.c          |    4 ++--
 drivers/video/console/fbcon.h          |    2 +-
 drivers/video/fbsysfs.c                |    2 +-
 drivers/video/i810/i810_main.c         |    4 ++--
 drivers/video/modedb.c                 |   33 +++++++++++++++++----------------
 drivers/video/nvidia/nvidia.c          |    8 ++++----
 drivers/video/riva/fbdev.c             |    5 +++--
 drivers/video/savage/savagefb_driver.c |   12 ++++++------
 include/linux/fb.h                     |   31 ++++++++++++++++---------------
 9 files changed, 52 insertions(+), 49 deletions(-)

--- ps3-linux.orig/drivers/video/console/fbcon.c
+++ ps3-linux/drivers/video/console/fbcon.c
@@ -2071,7 +2071,7 @@ static int fbcon_resize(struct vc_data *
 	y_diff = info->var.yres - var.yres;
 	if (x_diff < 0 || x_diff > virt_fw ||
 	    y_diff < 0 || y_diff > virt_fh) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
 		mode = fb_find_best_mode(&var, &info->modelist);
@@ -2975,7 +2975,7 @@ static void fbcon_new_modelist(struct fb
 	int i;
 	struct vc_data *vc;
 	struct fb_var_screeninfo var;
-	struct fb_videomode *mode;
+	const struct fb_videomode *mode;
 
 	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (registered_fb[con2fb_map[i]] != info)
--- ps3-linux.orig/drivers/video/console/fbcon.h
+++ ps3-linux/drivers/video/console/fbcon.h
@@ -48,7 +48,7 @@ struct display {
     struct fb_bitfield green;
     struct fb_bitfield blue;
     struct fb_bitfield transp;
-    struct fb_videomode *mode;
+    const struct fb_videomode *mode;
 };
 
 struct fbcon_ops {
--- ps3-linux.orig/drivers/video/fbsysfs.c
+++ ps3-linux/drivers/video/fbsysfs.c
@@ -175,7 +175,7 @@ static ssize_t store_modes(struct device
 
 	acquire_console_sem();
 	list_splice(&fb_info->modelist, &old_list);
-	fb_videomode_to_modelist((struct fb_videomode *)buf, i,
+	fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
 				 &fb_info->modelist);
 	if (fb_new_modelist(fb_info)) {
 		fb_destroy_modelist(&fb_info->modelist);
--- ps3-linux.orig/drivers/video/i810/i810_main.c
+++ ps3-linux/drivers/video/i810/i810_main.c
@@ -1049,7 +1049,7 @@ static int i810_check_params(struct fb_v
 		mode_valid = 1;
 
 	if (!mode_valid && info->monspecs.modedb_len) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -1919,7 +1919,7 @@ static void __devinit i810fb_find_init_m
 	fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
 				 &info->modelist);
 	if (specs->modedb != NULL) {
-		struct fb_videomode *m;
+		const struct fb_videomode *m;
 
 		if (xres && yres) {
 			if ((m = fb_find_best_mode(&var, &info->modelist))) {
--- ps3-linux.orig/drivers/video/modedb.c
+++ ps3-linux/drivers/video/modedb.c
@@ -668,7 +668,7 @@ done:
  * @var: pointer to struct fb_var_screeninfo
  */
 void fb_var_to_videomode(struct fb_videomode *mode,
-			 struct fb_var_screeninfo *var)
+			 const struct fb_var_screeninfo *var)
 {
 	u32 pixclock, hfreq, htotal, vtotal;
 
@@ -712,7 +712,7 @@ void fb_var_to_videomode(struct fb_video
  * @mode: pointer to struct fb_videomode
  */
 void fb_videomode_to_var(struct fb_var_screeninfo *var,
-			       struct fb_videomode *mode)
+			 const struct fb_videomode *mode)
 {
 	var->xres = mode->xres;
 	var->yres = mode->yres;
@@ -735,8 +735,8 @@ void fb_videomode_to_var(struct fb_var_s
  * RETURNS:
  * 1 if equal, 0 if not
  */
-int fb_mode_is_equal(struct fb_videomode *mode1,
-		     struct fb_videomode *mode2)
+int fb_mode_is_equal(const struct fb_videomode *mode1,
+		     const struct fb_videomode *mode2)
 {
 	return (mode1->xres         == mode2->xres &&
 		mode1->yres         == mode2->yres &&
@@ -768,8 +768,8 @@ int fb_mode_is_equal(struct fb_videomode
  * var->xres and var->yres.  If more than 1 videomode is found, will return
  * the videomode with the highest refresh rate
  */
-struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
-				       struct list_head *head)
+const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+					     struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -806,8 +806,8 @@ struct fb_videomode *fb_find_best_mode(s
  * If more than 1 videomode is found, will return the videomode with
  * the closest refresh rate.
  */
-struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
-					  struct list_head *head)
+const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+					        struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -845,8 +845,8 @@ struct fb_videomode *fb_find_nearest_mod
  * RETURNS:
  * struct fb_videomode, NULL if none found
  */
-struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
-				   struct list_head *head)
+const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+					 struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -870,7 +870,7 @@ struct fb_videomode *fb_match_mode(struc
  * NOTES:
  * Will only add unmatched mode entries
  */
-int fb_add_videomode(struct fb_videomode *mode, struct list_head *head)
+int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -905,7 +905,8 @@ int fb_add_videomode(struct fb_videomode
  * NOTES:
  * Will remove all matching mode entries
  */
-void fb_delete_videomode(struct fb_videomode *mode, struct list_head *head)
+void fb_delete_videomode(const struct fb_videomode *mode,
+			 struct list_head *head)
 {
 	struct list_head *pos, *n;
 	struct fb_modelist *modelist;
@@ -941,7 +942,7 @@ void fb_destroy_modelist(struct list_hea
  * @num: number of entries in array
  * @head: struct list_head of modelist
  */
-void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
 			      struct list_head *head)
 {
 	int i;
@@ -954,12 +955,12 @@ void fb_videomode_to_modelist(struct fb_
 	}
 }
 
-struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
-					  struct list_head *head)
+const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+					        struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
-	struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
+	const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
 	int first = 0;
 
 	if (!head->prev || !head->next || list_empty(head))
--- ps3-linux.orig/drivers/video/nvidia/nvidia.c
+++ ps3-linux/drivers/video/nvidia/nvidia.c
@@ -829,7 +829,7 @@ static int nvidiafb_check_var(struct fb_
 	}
 
 	if (!mode_valid) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -1046,10 +1046,10 @@ static int __devinit nvidia_set_fbinfo(s
 	}
 
 	if (specs->modedb != NULL) {
-		struct fb_videomode *modedb;
+		const struct fb_videomode *mode;
 
-		modedb = fb_find_best_display(specs, &info->modelist);
-		fb_videomode_to_var(&nvidiafb_default_var, modedb);
+		mode = fb_find_best_display(specs, &info->modelist);
+		fb_videomode_to_var(&nvidiafb_default_var, mode);
 		nvidiafb_default_var.bits_per_pixel = bpp;
 	} else if (par->fpWidth && par->fpHeight) {
 		char buf[16];
--- ps3-linux.orig/drivers/video/riva/fbdev.c
+++ ps3-linux/drivers/video/riva/fbdev.c
@@ -894,7 +894,8 @@ out:
 	return rc;
 }
 
-static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+static void riva_update_var(struct fb_var_screeninfo *var,
+			    const struct fb_videomode *modedb)
 {
 	NVTRACE_ENTER();
 	var->xres = var->xres_virtual = modedb->xres;
@@ -1148,7 +1149,7 @@ static int rivafb_release(struct fb_info
 
 static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct fb_videomode *mode;
+	const struct fb_videomode *mode;
 	struct riva_par *par = info->par;
 	int nom, den;		/* translating from pixels->bytes */
 	int mode_valid = 0;
--- ps3-linux.orig/drivers/video/savage/savagefb_driver.c
+++ ps3-linux/drivers/video/savage/savagefb_driver.c
@@ -833,7 +833,8 @@ static void savage_set_default_par(struc
 	vga_out8(0x3d5, cr66, par);
 }
 
-static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+static void savage_update_var(struct fb_var_screeninfo *var,
+			      const struct fb_videomode *modedb)
 {
 	var->xres = var->xres_virtual = modedb->xres;
 	var->yres = modedb->yres;
@@ -902,7 +903,7 @@ static int savagefb_check_var(struct fb_
 	}
 
 	if (!mode_valid) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -2206,11 +2207,10 @@ static int __devinit savagefb_probe(stru
 			     info->monspecs.modedb, info->monspecs.modedb_len,
 			     NULL, 8);
 	} else if (info->monspecs.modedb != NULL) {
-		struct fb_videomode *modedb;
+		const struct fb_videomode *mode;
 
-		modedb = fb_find_best_display(&info->monspecs,
-					      &info->modelist);
-		savage_update_var(&info->var, modedb);
+		mode = fb_find_best_display(&info->monspecs, &info->modelist);
+		savage_update_var(&info->var, mode);
 	}
 
 	/* maximize virtual vertical length */
--- ps3-linux.orig/include/linux/fb.h
+++ ps3-linux/include/linux/fb.h
@@ -945,25 +945,26 @@ extern unsigned char *fb_ddc_read(struct
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
 extern void fb_var_to_videomode(struct fb_videomode *mode,
-				struct fb_var_screeninfo *var);
+				const struct fb_var_screeninfo *var);
 extern void fb_videomode_to_var(struct fb_var_screeninfo *var,
-				struct fb_videomode *mode);
-extern int fb_mode_is_equal(struct fb_videomode *mode1,
-			    struct fb_videomode *mode2);
-extern int fb_add_videomode(struct fb_videomode *mode, struct list_head *head);
-extern void fb_delete_videomode(struct fb_videomode *mode,
+				const struct fb_videomode *mode);
+extern int fb_mode_is_equal(const struct fb_videomode *mode1,
+			    const struct fb_videomode *mode2);
+extern int fb_add_videomode(const struct fb_videomode *mode,
+			    struct list_head *head);
+extern void fb_delete_videomode(const struct fb_videomode *mode,
 				struct list_head *head);
-extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
-					  struct list_head *head);
-extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
-					      struct list_head *head);
-extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
-						 struct list_head *head);
+extern const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+						struct list_head *head);
+extern const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+						    struct list_head *head);
+extern const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+						       struct list_head *head);
 extern void fb_destroy_modelist(struct list_head *head);
-extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+extern void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
 				     struct list_head *head);
-extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
-						 struct list_head *head);
+extern const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+						       struct list_head *head);
 
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 3/9] fbdev modedb: make more pointer parameters const
@ 2007-01-25 17:49   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:49 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

fbdev modedb: make more input and output pointer parameters const

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/video/console/fbcon.c          |    4 ++--
 drivers/video/console/fbcon.h          |    2 +-
 drivers/video/fbsysfs.c                |    2 +-
 drivers/video/i810/i810_main.c         |    4 ++--
 drivers/video/modedb.c                 |   33 +++++++++++++++++----------------
 drivers/video/nvidia/nvidia.c          |    8 ++++----
 drivers/video/riva/fbdev.c             |    5 +++--
 drivers/video/savage/savagefb_driver.c |   12 ++++++------
 include/linux/fb.h                     |   31 ++++++++++++++++---------------
 9 files changed, 52 insertions(+), 49 deletions(-)

--- ps3-linux.orig/drivers/video/console/fbcon.c
+++ ps3-linux/drivers/video/console/fbcon.c
@@ -2071,7 +2071,7 @@ static int fbcon_resize(struct vc_data *
 	y_diff = info->var.yres - var.yres;
 	if (x_diff < 0 || x_diff > virt_fw ||
 	    y_diff < 0 || y_diff > virt_fh) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
 		mode = fb_find_best_mode(&var, &info->modelist);
@@ -2975,7 +2975,7 @@ static void fbcon_new_modelist(struct fb
 	int i;
 	struct vc_data *vc;
 	struct fb_var_screeninfo var;
-	struct fb_videomode *mode;
+	const struct fb_videomode *mode;
 
 	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (registered_fb[con2fb_map[i]] != info)
--- ps3-linux.orig/drivers/video/console/fbcon.h
+++ ps3-linux/drivers/video/console/fbcon.h
@@ -48,7 +48,7 @@ struct display {
     struct fb_bitfield green;
     struct fb_bitfield blue;
     struct fb_bitfield transp;
-    struct fb_videomode *mode;
+    const struct fb_videomode *mode;
 };
 
 struct fbcon_ops {
--- ps3-linux.orig/drivers/video/fbsysfs.c
+++ ps3-linux/drivers/video/fbsysfs.c
@@ -175,7 +175,7 @@ static ssize_t store_modes(struct device
 
 	acquire_console_sem();
 	list_splice(&fb_info->modelist, &old_list);
-	fb_videomode_to_modelist((struct fb_videomode *)buf, i,
+	fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
 				 &fb_info->modelist);
 	if (fb_new_modelist(fb_info)) {
 		fb_destroy_modelist(&fb_info->modelist);
--- ps3-linux.orig/drivers/video/i810/i810_main.c
+++ ps3-linux/drivers/video/i810/i810_main.c
@@ -1049,7 +1049,7 @@ static int i810_check_params(struct fb_v
 		mode_valid = 1;
 
 	if (!mode_valid && info->monspecs.modedb_len) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -1919,7 +1919,7 @@ static void __devinit i810fb_find_init_m
 	fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
 				 &info->modelist);
 	if (specs->modedb != NULL) {
-		struct fb_videomode *m;
+		const struct fb_videomode *m;
 
 		if (xres && yres) {
 			if ((m = fb_find_best_mode(&var, &info->modelist))) {
--- ps3-linux.orig/drivers/video/modedb.c
+++ ps3-linux/drivers/video/modedb.c
@@ -668,7 +668,7 @@ done:
  * @var: pointer to struct fb_var_screeninfo
  */
 void fb_var_to_videomode(struct fb_videomode *mode,
-			 struct fb_var_screeninfo *var)
+			 const struct fb_var_screeninfo *var)
 {
 	u32 pixclock, hfreq, htotal, vtotal;
 
@@ -712,7 +712,7 @@ void fb_var_to_videomode(struct fb_video
  * @mode: pointer to struct fb_videomode
  */
 void fb_videomode_to_var(struct fb_var_screeninfo *var,
-			       struct fb_videomode *mode)
+			 const struct fb_videomode *mode)
 {
 	var->xres = mode->xres;
 	var->yres = mode->yres;
@@ -735,8 +735,8 @@ void fb_videomode_to_var(struct fb_var_s
  * RETURNS:
  * 1 if equal, 0 if not
  */
-int fb_mode_is_equal(struct fb_videomode *mode1,
-		     struct fb_videomode *mode2)
+int fb_mode_is_equal(const struct fb_videomode *mode1,
+		     const struct fb_videomode *mode2)
 {
 	return (mode1->xres         == mode2->xres &&
 		mode1->yres         == mode2->yres &&
@@ -768,8 +768,8 @@ int fb_mode_is_equal(struct fb_videomode
  * var->xres and var->yres.  If more than 1 videomode is found, will return
  * the videomode with the highest refresh rate
  */
-struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
-				       struct list_head *head)
+const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+					     struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -806,8 +806,8 @@ struct fb_videomode *fb_find_best_mode(s
  * If more than 1 videomode is found, will return the videomode with
  * the closest refresh rate.
  */
-struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
-					  struct list_head *head)
+const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+					        struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -845,8 +845,8 @@ struct fb_videomode *fb_find_nearest_mod
  * RETURNS:
  * struct fb_videomode, NULL if none found
  */
-struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
-				   struct list_head *head)
+const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+					 struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -870,7 +870,7 @@ struct fb_videomode *fb_match_mode(struc
  * NOTES:
  * Will only add unmatched mode entries
  */
-int fb_add_videomode(struct fb_videomode *mode, struct list_head *head)
+int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -905,7 +905,8 @@ int fb_add_videomode(struct fb_videomode
  * NOTES:
  * Will remove all matching mode entries
  */
-void fb_delete_videomode(struct fb_videomode *mode, struct list_head *head)
+void fb_delete_videomode(const struct fb_videomode *mode,
+			 struct list_head *head)
 {
 	struct list_head *pos, *n;
 	struct fb_modelist *modelist;
@@ -941,7 +942,7 @@ void fb_destroy_modelist(struct list_hea
  * @num: number of entries in array
  * @head: struct list_head of modelist
  */
-void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
 			      struct list_head *head)
 {
 	int i;
@@ -954,12 +955,12 @@ void fb_videomode_to_modelist(struct fb_
 	}
 }
 
-struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
-					  struct list_head *head)
+const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+					        struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
-	struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
+	const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
 	int first = 0;
 
 	if (!head->prev || !head->next || list_empty(head))
--- ps3-linux.orig/drivers/video/nvidia/nvidia.c
+++ ps3-linux/drivers/video/nvidia/nvidia.c
@@ -829,7 +829,7 @@ static int nvidiafb_check_var(struct fb_
 	}
 
 	if (!mode_valid) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -1046,10 +1046,10 @@ static int __devinit nvidia_set_fbinfo(s
 	}
 
 	if (specs->modedb != NULL) {
-		struct fb_videomode *modedb;
+		const struct fb_videomode *mode;
 
-		modedb = fb_find_best_display(specs, &info->modelist);
-		fb_videomode_to_var(&nvidiafb_default_var, modedb);
+		mode = fb_find_best_display(specs, &info->modelist);
+		fb_videomode_to_var(&nvidiafb_default_var, mode);
 		nvidiafb_default_var.bits_per_pixel = bpp;
 	} else if (par->fpWidth && par->fpHeight) {
 		char buf[16];
--- ps3-linux.orig/drivers/video/riva/fbdev.c
+++ ps3-linux/drivers/video/riva/fbdev.c
@@ -894,7 +894,8 @@ out:
 	return rc;
 }
 
-static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+static void riva_update_var(struct fb_var_screeninfo *var,
+			    const struct fb_videomode *modedb)
 {
 	NVTRACE_ENTER();
 	var->xres = var->xres_virtual = modedb->xres;
@@ -1148,7 +1149,7 @@ static int rivafb_release(struct fb_info
 
 static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct fb_videomode *mode;
+	const struct fb_videomode *mode;
 	struct riva_par *par = info->par;
 	int nom, den;		/* translating from pixels->bytes */
 	int mode_valid = 0;
--- ps3-linux.orig/drivers/video/savage/savagefb_driver.c
+++ ps3-linux/drivers/video/savage/savagefb_driver.c
@@ -833,7 +833,8 @@ static void savage_set_default_par(struc
 	vga_out8(0x3d5, cr66, par);
 }
 
-static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+static void savage_update_var(struct fb_var_screeninfo *var,
+			      const struct fb_videomode *modedb)
 {
 	var->xres = var->xres_virtual = modedb->xres;
 	var->yres = modedb->yres;
@@ -902,7 +903,7 @@ static int savagefb_check_var(struct fb_
 	}
 
 	if (!mode_valid) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -2206,11 +2207,10 @@ static int __devinit savagefb_probe(stru
 			     info->monspecs.modedb, info->monspecs.modedb_len,
 			     NULL, 8);
 	} else if (info->monspecs.modedb != NULL) {
-		struct fb_videomode *modedb;
+		const struct fb_videomode *mode;
 
-		modedb = fb_find_best_display(&info->monspecs,
-					      &info->modelist);
-		savage_update_var(&info->var, modedb);
+		mode = fb_find_best_display(&info->monspecs, &info->modelist);
+		savage_update_var(&info->var, mode);
 	}
 
 	/* maximize virtual vertical length */
--- ps3-linux.orig/include/linux/fb.h
+++ ps3-linux/include/linux/fb.h
@@ -945,25 +945,26 @@ extern unsigned char *fb_ddc_read(struct
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
 extern void fb_var_to_videomode(struct fb_videomode *mode,
-				struct fb_var_screeninfo *var);
+				const struct fb_var_screeninfo *var);
 extern void fb_videomode_to_var(struct fb_var_screeninfo *var,
-				struct fb_videomode *mode);
-extern int fb_mode_is_equal(struct fb_videomode *mode1,
-			    struct fb_videomode *mode2);
-extern int fb_add_videomode(struct fb_videomode *mode, struct list_head *head);
-extern void fb_delete_videomode(struct fb_videomode *mode,
+				const struct fb_videomode *mode);
+extern int fb_mode_is_equal(const struct fb_videomode *mode1,
+			    const struct fb_videomode *mode2);
+extern int fb_add_videomode(const struct fb_videomode *mode,
+			    struct list_head *head);
+extern void fb_delete_videomode(const struct fb_videomode *mode,
 				struct list_head *head);
-extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
-					  struct list_head *head);
-extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
-					      struct list_head *head);
-extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
-						 struct list_head *head);
+extern const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+						struct list_head *head);
+extern const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+						    struct list_head *head);
+extern const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+						       struct list_head *head);
 extern void fb_destroy_modelist(struct list_head *head);
-extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+extern void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
 				     struct list_head *head);
-extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
-						 struct list_head *head);
+extern const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+						       struct list_head *head);
 
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 4/9] fb_videomode_to_var: reset virtual screen parameters
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:49   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:49 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

fb_videomode_to_var(): reset the virtual screen parameters when converting from
an fb_videomode to an fb_var_screeninfo.

Without this the old virtual screen parameters are kept. Hence you cannot
switch to a video mode with a lower resolution on frame buffer devices that
don't support virtual screens and panning, as values are not supposed to be
rounded down when they don't fit.

I also reordered the assignments to match the order of the individual members.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/video/modedb.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

--- ps3-linux.orig/drivers/video/modedb.c
+++ ps3-linux/drivers/video/modedb.c
@@ -716,13 +716,17 @@ void fb_videomode_to_var(struct fb_var_s
 {
 	var->xres = mode->xres;
 	var->yres = mode->yres;
+	var->xres_virtual = mode->xres;
+	var->yres_virtual = mode->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
 	var->pixclock = mode->pixclock;
 	var->left_margin = mode->left_margin;
-	var->hsync_len = mode->hsync_len;
-	var->vsync_len = mode->vsync_len;
 	var->right_margin = mode->right_margin;
 	var->upper_margin = mode->upper_margin;
 	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
 	var->sync = mode->sync;
 	var->vmode = mode->vmode & FB_VMODE_MASK;
 }

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 4/9] fb_videomode_to_var: reset virtual screen parameters
@ 2007-01-25 17:49   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:49 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

fb_videomode_to_var(): reset the virtual screen parameters when converting from
an fb_videomode to an fb_var_screeninfo.

Without this the old virtual screen parameters are kept. Hence you cannot
switch to a video mode with a lower resolution on frame buffer devices that
don't support virtual screens and panning, as values are not supposed to be
rounded down when they don't fit.

I also reordered the assignments to match the order of the individual members.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/video/modedb.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

--- ps3-linux.orig/drivers/video/modedb.c
+++ ps3-linux/drivers/video/modedb.c
@@ -716,13 +716,17 @@ void fb_videomode_to_var(struct fb_var_s
 {
 	var->xres = mode->xres;
 	var->yres = mode->yres;
+	var->xres_virtual = mode->xres;
+	var->yres_virtual = mode->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
 	var->pixclock = mode->pixclock;
 	var->left_margin = mode->left_margin;
-	var->hsync_len = mode->hsync_len;
-	var->vsync_len = mode->vsync_len;
 	var->right_margin = mode->right_margin;
 	var->upper_margin = mode->upper_margin;
 	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
 	var->sync = mode->sync;
 	var->vmode = mode->vmode & FB_VMODE_MASK;
 }

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:50   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:50 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

Preallocate bootmem memory for the PS3 frame buffer device, which needs a
large block of physically-contiguous memory. The size of this memory block is
configurable:
  - The config option CONFIG_FB_PS3_DEFAULT_SIZE_M allows to specify the
    default amount of memory (in MiB) allocated to the virtual frame buffer.
  - The early boot parameter `ps3fb=xxx' allows to override the default value.
    It will be rounded up to a multiple of 1 MiB, if needed.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/setup.c |   42 +++++++++++++++++++++++++++++++++++++
 include/asm-powerpc/ps3.h          |    9 +++++++
 2 files changed, 51 insertions(+)

--- ps3-linux.orig/arch/powerpc/platforms/ps3/setup.c
+++ ps3-linux/arch/powerpc/platforms/ps3/setup.c
@@ -24,6 +24,7 @@
 #include <linux/root_dev.h>
 #include <linux/console.h>
 #include <linux/kexec.h>
+#include <linux/bootmem.h>
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
@@ -93,6 +94,46 @@ static void ps3_panic(char *str)
 	for (;;) ;
 }
 
+
+static void prealloc(struct ps3_prealloc *p)
+{
+	if (!p->size)
+		return;
+
+	p->address = __alloc_bootmem(p->size, p->align, __pa(MAX_DMA_ADDRESS));
+	if (!p->address) {
+		printk(KERN_ERR "%s: Cannot allocate %s\n", __FUNCTION__,
+		       p->name);
+		return;
+	}
+
+	printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size,
+	       p->address);
+}
+
+#ifdef CONFIG_FB_PS3
+struct ps3_prealloc ps3fb_videomemory = {
+    .name = "ps3fb videomemory",
+    .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+    .align = 1024*1024			/* the GPU requires 1 MiB alignment */
+};
+#define prealloc_ps3fb_videomemory()	prealloc(&ps3fb_videomemory)
+
+static int __init early_parse_ps3fb(char *p)
+{
+	if (!p)
+		return 1;
+
+	ps3fb_videomemory.size = _ALIGN_UP(memparse(p, &p),
+					   ps3fb_videomemory.align);
+	return 0;
+}
+early_param("ps3fb", early_parse_ps3fb);
+#else
+#define prealloc_ps3fb_videomemory()	do { } while (0)
+#endif
+
+
 static void __init ps3_setup_arch(void)
 {
 	struct ps3_firmware_version v;
@@ -116,6 +157,7 @@ static void __init ps3_setup_arch(void)
 
 	ppc_md.power_save = ps3_power_save;
 
+	prealloc_ps3fb_videomemory();
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
--- ps3-linux.orig/include/asm-powerpc/ps3.h
+++ ps3-linux/include/asm-powerpc/ps3.h
@@ -500,4 +500,13 @@ static inline void *ps3_system_bus_get_d
 
 extern struct bus_type ps3_system_bus_type;
 
+struct ps3_prealloc {
+    const char *name;
+    void *address;
+    unsigned long size;
+    unsigned long align;
+};
+
+extern struct ps3_prealloc ps3fb_videomemory;
+
 #endif

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
@ 2007-01-25 17:50   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:50 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

Preallocate bootmem memory for the PS3 frame buffer device, which needs a
large block of physically-contiguous memory. The size of this memory block is
configurable:
  - The config option CONFIG_FB_PS3_DEFAULT_SIZE_M allows to specify the
    default amount of memory (in MiB) allocated to the virtual frame buffer.
  - The early boot parameter `ps3fb=xxx' allows to override the default value.
    It will be rounded up to a multiple of 1 MiB, if needed.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/setup.c |   42 +++++++++++++++++++++++++++++++++++++
 include/asm-powerpc/ps3.h          |    9 +++++++
 2 files changed, 51 insertions(+)

--- ps3-linux.orig/arch/powerpc/platforms/ps3/setup.c
+++ ps3-linux/arch/powerpc/platforms/ps3/setup.c
@@ -24,6 +24,7 @@
 #include <linux/root_dev.h>
 #include <linux/console.h>
 #include <linux/kexec.h>
+#include <linux/bootmem.h>
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
@@ -93,6 +94,46 @@ static void ps3_panic(char *str)
 	for (;;) ;
 }
 
+
+static void prealloc(struct ps3_prealloc *p)
+{
+	if (!p->size)
+		return;
+
+	p->address = __alloc_bootmem(p->size, p->align, __pa(MAX_DMA_ADDRESS));
+	if (!p->address) {
+		printk(KERN_ERR "%s: Cannot allocate %s\n", __FUNCTION__,
+		       p->name);
+		return;
+	}
+
+	printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size,
+	       p->address);
+}
+
+#ifdef CONFIG_FB_PS3
+struct ps3_prealloc ps3fb_videomemory = {
+    .name = "ps3fb videomemory",
+    .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+    .align = 1024*1024			/* the GPU requires 1 MiB alignment */
+};
+#define prealloc_ps3fb_videomemory()	prealloc(&ps3fb_videomemory)
+
+static int __init early_parse_ps3fb(char *p)
+{
+	if (!p)
+		return 1;
+
+	ps3fb_videomemory.size = _ALIGN_UP(memparse(p, &p),
+					   ps3fb_videomemory.align);
+	return 0;
+}
+early_param("ps3fb", early_parse_ps3fb);
+#else
+#define prealloc_ps3fb_videomemory()	do { } while (0)
+#endif
+
+
 static void __init ps3_setup_arch(void)
 {
 	struct ps3_firmware_version v;
@@ -116,6 +157,7 @@ static void __init ps3_setup_arch(void)
 
 	ppc_md.power_save = ps3_power_save;
 
+	prealloc_ps3fb_videomemory();
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
--- ps3-linux.orig/include/asm-powerpc/ps3.h
+++ ps3-linux/include/asm-powerpc/ps3.h
@@ -500,4 +500,13 @@ static inline void *ps3_system_bus_get_d
 
 extern struct bus_type ps3_system_bus_type;
 
+struct ps3_prealloc {
+    const char *name;
+    void *address;
+    unsigned long size;
+    unsigned long align;
+};
+
+extern struct ps3_prealloc ps3fb_videomemory;
+
 #endif

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 6/9] ps3: Virtual Frame Buffer Driver
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:50   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:50 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

Add the PS3 Virtual Frame Buffer Driver.

As the actual graphics hardware cannot be accessed directly by Linux,
ps3fb uses a virtual frame buffer in main memory. The actual screen image is
copied to graphics memory by the GPU on every vertical blank, by making a
hypervisor call.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/video/Kconfig       |   19 
 drivers/video/Makefile      |    1 
 drivers/video/ps3fb.c       | 1266 ++++++++++++++++++++++++++++++++++++++++++++
 include/asm-powerpc/ps3fb.h |   42 +
 4 files changed, 1328 insertions(+)

--- ps3-linux.orig/drivers/video/Kconfig
+++ ps3-linux/drivers/video/Kconfig
@@ -1625,6 +1625,25 @@ config FB_IBM_GXT4500
 	  Say Y here to enable support for the IBM GXT4500P display
 	  adaptor, found on some IBM System P (pSeries) machines.
 
+config FB_PS3
+	bool "PS3 GPU framebuffer driver"
+	depends on FB && PS3_PS3AV=y
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Include support for the virtual frame buffer in the PS3 platform.
+
+config FB_PS3_DEFAULT_SIZE_M
+	int "PS3 default frame buffer size (in MiB)"
+	depends on FB_PS3
+	default 18
+	---help---
+	  This is the default size (in MiB) of the virtual frame buffer in
+	  the PS3.
+	  The default value can be overridden on the kernel command line
+	  using the "ps3fb" option (e.g. "ps3fb=9M");
+
 config FB_VIRTUAL
 	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
 	depends on FB
--- ps3-linux.orig/drivers/video/Makefile
+++ ps3-linux/drivers/video/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_FB_S3C2410)	  += s3c2410fb.
 obj-$(CONFIG_FB_PNX4008_DUM)	  += pnx4008/
 obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
 obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o
+obj-$(CONFIG_FB_PS3)		  += ps3fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
--- /dev/null
+++ ps3-linux/drivers/video/ps3fb.c
@@ -0,0 +1,1266 @@
+/*
+ * linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device
+ *
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ *  this file is based on :
+ *
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
+ *
+ *      Copyright (C) 2002 James Simmons
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/console.h>
+#include <linux/ioctl.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <asm/time.h>
+
+#include <asm/abs_addr.h>
+#include <asm/lv1call.h>
+#include <asm/ps3av.h>
+#include <asm/ps3fb.h>
+#include <asm/ps3.h>
+
+#ifdef PS3FB_DEBUG
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define PS3FB_DEV                                   0	/* /dev/fb0 */
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET    0x100
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC        0x101
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP        0x102
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP            0x600
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT             0x601
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT_SYNC        0x602
+
+#define L1GPU_DISPLAY_SYNC_HSYNC                    1
+#define L1GPU_DISPLAY_SYNC_VSYNC                    2
+
+#define DDR_SIZE                    (0)	/* used no ddr */
+#define GPU_OFFSET                  (64 * 1024)
+#define GPU_IOIF                    (0x0d000000UL)
+
+#define PS3FB_FULL_MODE_BIT         0x80
+
+#define GPU_INTR_STATUS_VSYNC_0     0	/* vsync on head A */
+#define GPU_INTR_STATUS_VSYNC_1     1	/* vsync on head B */
+#define GPU_INTR_STATUS_FLIP_0      3	/* flip head A */
+#define GPU_INTR_STATUS_FLIP_1      4	/* flip head B */
+#define GPU_INTR_STATUS_QUEUE_0     5	/* queue head A */
+#define GPU_INTR_STATUS_QUEUE_1     6	/* queue head B */
+
+#define GPU_DRIVER_INFO_VERSION     0x211
+
+/* gpu internals */
+struct display_head {
+	u64 be_time_stamp;
+	u32 status;
+	u32 offset;
+	u32 res1;
+	u32 res2;
+	u32 field;
+	u32 reserved1;
+
+	u64 res3;
+	u32 raster;
+
+	u64 vblank_count;
+	u32 field_vsync;
+	u32 reserved2;
+};
+
+struct gpu_irq {
+	u32 irq_outlet;
+	u32 status;
+	u32 mask;
+	u32 video_cause;
+	u32 graph_cause;
+	u32 user_cause;
+
+	u32 res1;
+	u64 res2;
+
+	u32 reserved[4];
+};
+
+struct gpu_driver_info {
+	u32 version_driver;
+	u32 version_gpu;
+	u32 memory_size;
+	u32 hardware_channel;
+
+	u32 nvcore_frequency;
+	u32 memory_frequency;
+
+	u32 reserved[1063];
+	struct display_head display_head[8];
+	struct gpu_irq irq;
+};
+
+struct ps3fb_priv {
+	unsigned long videomemory_phys;
+	unsigned long videomemorysize;
+	unsigned int irq_no;
+	void *dev;
+
+	u64 context_handle, memory_handle;
+	void *xdr_ea;
+	struct gpu_driver_info *dinfo;
+	struct semaphore sem;
+	u32 res_index;
+
+	u64 vblank_count;	/* frame count */
+	wait_queue_head_t wait_vsync;
+
+	u32 num_frames;		/* num of frame buffers */
+	atomic_t ext_flip;	/* on/off flip with vsync */
+	atomic_t f_count;	/* fb_open count */
+	int is_blanked;
+};
+static struct ps3fb_priv ps3fb;
+
+struct ps3fb_res_table {
+	u32 xres;
+	u32 yres;
+	u32 xoff;
+	u32 yoff;
+	u32 type;
+};
+#define PS3FB_RES_FULL 1
+static const struct ps3fb_res_table ps3fb_res[] = {
+	/* res_x,y   margin_x,y  full */
+	{  720,  480,  72,  48 , 0},
+	{  720,  576,  72,  58 , 0},
+	{ 1280,  720,  78,  38 , 0},
+	{ 1920, 1080, 116,  58 , 0},
+	/* full mode */
+	{  720,  480,   0,   0 , PS3FB_RES_FULL},
+	{  720,  576,   0,   0 , PS3FB_RES_FULL},
+	{ 1280,  720,   0,   0 , PS3FB_RES_FULL},
+	{ 1920, 1080,   0,   0 , PS3FB_RES_FULL},
+	/* vesa: normally full mode */
+	{ 1280,  768,   0,   0 , 0},
+	{ 1280, 1024,   0,   0 , 0},
+	{ 1920, 1200,   0,   0 , 0},
+	{    0,    0,   0,   0 , 0} };
+
+/* default resolution */
+#define GPU_RES_INDEX 0		/* 720 x 480 */
+
+static const struct fb_videomode ps3fb_modedb[] = {
+    /* 60 Hz broadcast modes (modes "1" to "5") */
+    {
+        /* 480i */
+        "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 480p */
+        "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080i */
+        "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (modes "6" to "10") */
+    {
+        /* 576i */
+        "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 576p */
+        "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080 */
+        "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* VESA modes (modes "11" to "13") */
+    {
+	/* WXGA */
+	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* SXGA */
+	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* WUXGA */
+	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
+	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    },
+
+    /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */
+    {
+	/* 480if */
+	"480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 480pf */
+	"480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */
+    {
+	/* 576if */
+	"576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 576pf */
+	"576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080f", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }
+};
+
+
+    /*
+     *  RAM we reserve for the frame buffer. This defines the maximum screen
+     *  size
+     *
+     *  The default can be overridden if the driver is compiled as a module
+     */
+
+#define HEAD_A
+#define HEAD_B
+
+#define X_OFF(i)	(ps3fb_res[i].xoff)	/* left/right margin (pixel) */
+#define Y_OFF(i)	(ps3fb_res[i].yoff)	/* top/bottom margin (pixel) */
+#define WIDTH(i)	(ps3fb_res[i].xres)	/* width of FB */
+#define HEIGHT(i)	(ps3fb_res[i].yres)	/* height of FB */
+#define BPP	4		/* number of bytes per pixel */
+#define VP_OFF(i)	(WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP)
+#define FB_OFF(i)	(GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
+
+static int ps3fb_mode = 0;
+module_param(ps3fb_mode, bool, 0);
+
+static char *mode_option __initdata = NULL;
+
+
+static int ps3fb_get_res_table(u32 xres, u32 yres)
+{
+	int i, full_mode;
+	u32 x, y, f = 0;
+
+	full_mode = (ps3fb_mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0;
+	for (i = 0;; i++) {
+		x = ps3fb_res[i].xres;
+		y = ps3fb_res[i].yres;
+		f = ps3fb_res[i].type;
+		if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL) {
+			continue;
+		}
+		if (x == 0) {
+			DPRINTK("ERROR: ps3fb_get_res_table()\n");
+			return -1;
+		}
+		if (x == xres && (yres == 0 || y == yres))
+			break;
+		x = x - 2 * ps3fb_res[i].xoff;
+		y = y - 2 * ps3fb_res[i].yoff;
+		if (x == xres && (yres == 0 || y == yres))
+			break;
+	}
+	return i;
+}
+
+static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,
+				    u32 *line_length)
+{
+	unsigned int i, mode;
+
+	for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++)
+		if (var->xres == ps3fb_modedb[i].xres &&
+		    var->yres == ps3fb_modedb[i].yres &&
+		    var->pixclock == ps3fb_modedb[i].pixclock &&
+		    var->hsync_len == ps3fb_modedb[i].hsync_len &&
+		    var->vsync_len == ps3fb_modedb[i].vsync_len &&
+		    var->left_margin == ps3fb_modedb[i].left_margin &&
+		    var->right_margin == ps3fb_modedb[i].right_margin &&
+		    var->upper_margin == ps3fb_modedb[i].upper_margin &&
+		    var->lower_margin == ps3fb_modedb[i].lower_margin &&
+		    var->sync == ps3fb_modedb[i].sync &&
+		    (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) {
+			/* Cropped broadcast modes use the full line_length */
+			*line_length =
+			    ps3fb_modedb[i < 10 ? i + 13 : i].xres * 4;
+			/* Full broadcast modes have the full mode bit set */
+			mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
+
+			DPRINTK("ps3fb_find_mode: mode %u\n", mode);
+			return mode;
+		}
+
+	DPRINTK("ps3fb_find_mode: mode not found\n");
+	return 0;
+
+}
+
+static const struct fb_videomode *ps3fb_default_mode(void)
+{
+	u32 mode = ps3fb_mode & PS3AV_MODE_MASK;
+	u32 flags = ps3fb_mode & ~PS3AV_MODE_MASK;
+
+	if (mode < 1 || mode > 13)
+		return NULL;
+
+	if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) {
+		/* Full broadcast mode */
+		return &ps3fb_modedb[mode + 12];
+	}
+
+	return &ps3fb_modedb[mode - 1];
+}
+
+static int ps3fb_sync(u32 frame)
+{
+	int i;
+	u32 xres, yres;
+	u64 head, fb_ioif, offset;
+	u64 sync = 1;
+	int status;
+
+	i = ps3fb.res_index;
+	xres = ps3fb_res[i].xres;
+	yres = ps3fb_res[i].yres;
+
+	if (frame > ps3fb.num_frames - 1) {
+		printk(KERN_WARNING "%s: invalid frame number (%u)\n",
+		       __FUNCTION__, frame);
+		return -EINVAL;
+	}
+	offset = xres * yres * BPP * frame;
+
+	fb_ioif = GPU_IOIF + FB_OFF(i) + offset;
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
+					   offset, fb_ioif,
+					   (sync << 32) | (xres << 16) | yres,
+					   xres * BPP);	/* line_length */
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
+		       __FUNCTION__, status);
+#ifdef HEAD_A
+	head = 0;
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
+					   head, offset, 0, 0);
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __FUNCTION__, status);
+#endif
+#ifdef HEAD_B
+	head = 1;
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
+					   head, offset, 0, 0);
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __FUNCTION__, status);
+#endif
+	return 0;
+}
+
+
+static int ps3fb_open(struct fb_info *info, int user)
+{
+	atomic_inc(&ps3fb.f_count);
+	return 0;
+}
+
+static int ps3fb_release(struct fb_info *info, int user)
+{
+	if (atomic_dec_and_test(&ps3fb.f_count)) {
+		if (atomic_read(&ps3fb.ext_flip)) {
+			atomic_set(&ps3fb.ext_flip, 0);
+			ps3fb_sync(0);	/* single buffer */
+		}
+	}
+	return 0;
+}
+
+    /*
+     *  Setting the video mode has been split into two parts.
+     *  First part, xxxfb_check_var, must not write anything
+     *  to hardware, it should only verify and adjust var.
+     *  This means it doesn't alter par but it does use hardware
+     *  data from it to check this var.
+     */
+
+static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u32 line_length;
+	int mode;
+	int i;
+
+	DPRINTK("var->xres:%u info->var.xres:%u\n", var->xres, info->var.xres);
+	DPRINTK("var->yres:%u info->var.yres:%u\n", var->yres, info->var.yres);
+
+	/* FIXME For now we do exact matches only */
+	mode = ps3fb_find_mode(var, &line_length);
+	if (!mode)
+		return -EINVAL;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/* Virtual screen and panning are not supported */
+	if (var->xres_virtual > var->xres || var->yres_virtual > var->yres ||
+	    var->xoffset || var->yoffset) {
+		DPRINTK("Virtual screen and panning are not supported\n");
+		return -EINVAL;
+	}
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	/* We support ARGB8888 only */
+	if (var->bits_per_pixel > 32 || var->grayscale ||
+	    var->red.offset > 16 || var->green.offset > 8 ||
+	    var->blue.offset > 0 || var->transp.offset > 24 ||
+	    var->red.length > 8 || var->green.length > 8 ||
+	    var->blue.length > 8 || var->transp.length > 8 ||
+	    var->red.msb_right || var->green.msb_right ||
+	    var->blue.msb_right || var->transp.msb_right || var->nonstd) {
+		DPRINTK("We support ARGB8888 only\n");
+		return -EINVAL;
+	}
+
+	var->bits_per_pixel = 32;
+	var->red.offset = 16;
+	var->green.offset = 8;
+	var->blue.offset = 0;
+	var->transp.offset = 24;
+	var->red.length = 8;
+	var->green.length = 8;
+	var->blue.length = 8;
+	var->transp.length = 8;
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	/* Rotation is not supported */
+	if (var->rotate) {
+		DPRINTK("Rotation is not supported\n");
+		return -EINVAL;
+	}
+
+	/* Memory limit */
+	i = ps3fb_get_res_table(var->xres, var->yres);
+	if (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP > ps3fb.videomemorysize) {
+		DPRINTK("Not enough memory\n");
+		return -ENOMEM;
+	}
+
+	var->height = -1;
+	var->width = -1;
+
+	return 0;
+}
+
+/* This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
+ */
+static int ps3fb_set_par(struct fb_info *info)
+{
+	unsigned int mode;
+	int i;
+	unsigned long offset;
+	static int first = 1;
+
+	DPRINTK("xres:%d xv:%d yres:%d yv:%d clock:%d\n",
+		info->var.xres, info->var.xres_virtual,
+		info->var.yres, info->var.yres_virtual, info->var.pixclock);
+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
+	ps3fb.res_index = i;
+
+	mode = ps3fb_find_mode(&info->var, &info->fix.line_length);
+	if (!mode)
+		return -EINVAL;
+
+	offset = FB_OFF(i) + VP_OFF(i);
+	info->fix.smem_len = ps3fb.videomemorysize-offset;
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+	memset(ps3fb.xdr_ea, 0, ps3fb.videomemorysize);
+
+	ps3fb.num_frames = ps3fb.videomemorysize/
+			   (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
+
+	/* Keep the special bits we cannot set using fb_var_screeninfo */
+	ps3fb_mode = (ps3fb_mode & ~PS3AV_MODE_MASK) | mode;
+
+	if (ps3av_set_video_mode(ps3fb_mode, first))
+		return -EINVAL;
+
+	first = 0;
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int ps3fb_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp, struct fb_info *info)
+{
+	if (regno >= 16)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	transp >>= 8;
+
+	((u32 *)info->pseudo_palette)[regno] = transp << 24 | red << 16 |
+					       green << 8 | blue;
+	return 0;
+}
+
+    /*
+     *  Most drivers don't need their own mmap function
+     */
+
+static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	int i;
+
+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
+	if (i == -1)
+		return -EINVAL;
+
+	if (offset + size > info->fix.smem_len)
+		return -EINVAL;
+	offset += ps3fb.videomemory_phys + FB_OFF(i) + VP_OFF(i);
+	if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
+			    size, vma->vm_page_prot))
+		return -EAGAIN;
+	printk(KERN_DEBUG "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", offset,
+	       vma->vm_start);
+	return 0;
+}
+
+    /*
+     * Blank the display
+     */
+
+static int ps3fb_blank(int blank, struct fb_info *info)
+{
+	int retval = 0;
+
+	DPRINTK("%s: blank:%d\n", __FUNCTION__, blank);
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		retval = ps3av_video_mute(1);	/* mute on */
+		if (!retval)
+			ps3fb.is_blanked = 1;
+		break;
+	default:		/* unblank */
+		retval = ps3av_video_mute(0);	/* mute off */
+		if (!retval)
+			ps3fb.is_blanked = 0;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fb_get_vblank(struct fb_vblank *vblank)
+{
+	memset(vblank, 0, sizeof(&vblank));
+	vblank->flags = FB_VBLANK_HAVE_VSYNC;
+	return 0;
+}
+
+int ps3fb_wait_for_vsync(u32 crtc)
+{
+	int ret;
+	u64 count;
+
+	count = ps3fb.vblank_count;
+	ret = wait_event_interruptible_timeout(ps3fb.wait_vsync,
+					       count != ps3fb.vblank_count,
+					       HZ / 10);
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3fb_wait_for_vsync);
+
+int ps3fb_flip_ctl(int on)
+{
+	if (on) {
+		if (atomic_read(&ps3fb.ext_flip) > 0) {
+			atomic_dec(&ps3fb.ext_flip);
+		}
+	} else {
+		atomic_inc(&ps3fb.ext_flip);
+	}
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3fb_flip_ctl);
+
+    /*
+     * ioctl
+     */
+
+static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	u32 val, old_mode;
+	int retval = 0;
+
+	switch (cmd) {
+	case FBIOGET_VBLANK:
+		{
+			struct fb_vblank vblank;
+			DPRINTK("FBIOGET_VBLANK:\n");
+			retval = ps3fb_get_vblank(&vblank);
+			if (!retval) {
+				if (copy_to_user(argp, &vblank,
+						 sizeof(vblank))) {
+					retval = -EFAULT;
+				}
+			}
+			break;
+		}
+
+	case FBIO_WAITFORVSYNC:
+		{
+			u32 crt;
+			DPRINTK("FBIO_WAITFORVSYNC:\n");
+			if (get_user(crt, (u32 __user *) arg)) {
+				retval = -EFAULT;
+				break;
+			}
+			retval = ps3fb_wait_for_vsync(crt);
+			break;
+		}
+
+	case PS3FB_IOCTL_SETMODE:
+		{
+			const struct fb_videomode *mode;
+			struct fb_var_screeninfo var;
+
+			if (copy_from_user(&val, argp, sizeof(val))) {
+				retval = -EFAULT;
+				break;
+			}
+			DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
+			retval = -EINVAL;
+			old_mode = ps3fb_mode;
+			ps3fb_mode = val;
+			mode = ps3fb_default_mode();
+			if (mode) {
+				var = info->var;
+				fb_videomode_to_var(&var, mode);
+				acquire_console_sem();
+				info->flags |= FBINFO_MISC_USEREVENT;
+				/* Force, in case only special bits changed */
+				var.activate |= FB_ACTIVATE_FORCE;
+				retval = fb_set_var(info, &var);
+				info->flags &= ~FBINFO_MISC_USEREVENT;
+				release_console_sem();
+			}
+			if (retval)
+				ps3fb_mode = old_mode;
+			break;
+		}
+
+	case PS3FB_IOCTL_GETMODE:
+		val = ps3av_get_mode();
+		DPRINTK("PS3FB_IOCTL_GETMODE:%x\n", val);
+		if (copy_to_user(argp, &val, sizeof(val))) {
+			retval = -EFAULT;
+		}
+		break;
+
+	case PS3FB_IOCTL_SCREENINFO:
+		{
+			struct ps3fb_ioctl_res res;
+			int i = ps3fb.res_index;
+			DPRINTK("PS3FB_IOCTL_SCREENINFO:\n");
+			res.xres = ps3fb_res[i].xres;
+			res.yres = ps3fb_res[i].yres;
+			res.xoff = ps3fb_res[i].xoff;
+			res.yoff = ps3fb_res[i].yoff;
+			res.num_frames = ps3fb.num_frames;
+			if (copy_to_user(argp, &res, sizeof(res))) {
+				retval = -EFAULT;
+			}
+			break;
+		}
+
+	case PS3FB_IOCTL_ON:
+		DPRINTK("PS3FB_IOCTL_ON:\n");
+		atomic_inc(&ps3fb.ext_flip);
+		break;
+
+	case PS3FB_IOCTL_OFF:
+		DPRINTK("PS3FB_IOCTL_OFF:\n");
+		if (atomic_read(&ps3fb.ext_flip) > 0) {
+			atomic_dec(&ps3fb.ext_flip);
+		}
+		break;
+
+	case PS3FB_IOCTL_FSEL:
+		if (copy_from_user(&val, argp, sizeof(val))) {
+			retval = -EFAULT;
+			break;
+		}
+		DPRINTK("PS3FB_IOCTL_FSEL:%d\n", val);
+		retval = ps3fb_sync(val);
+		break;
+
+	default:
+		retval = -ENOTTY;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fbd(void *arg)
+{
+	daemonize("ps3fbd");
+	for (;;) {
+		down(&ps3fb.sem);
+		if (atomic_read(&ps3fb.ext_flip) == 0)
+			ps3fb_sync(0);	/* single buffer */
+	}
+	return 0;
+}
+
+static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
+{
+	u64 v1;
+	int status;
+	struct display_head *head = &ps3fb.dinfo->display_head[1];
+
+	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n",
+		       __FUNCTION__, status);
+		return IRQ_NONE;
+	}
+
+	if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
+		/* VSYNC */
+		ps3fb.vblank_count = head->vblank_count;
+		if (!ps3fb.is_blanked)
+			up(&ps3fb.sem);
+		wake_up_interruptible(&ps3fb.wait_vsync);
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifndef MODULE
+static int __init ps3fb_setup(char *options)
+{
+	char *this_opt;
+	int mode = 0;
+
+	if (!options || !*options)
+		return 0;	/* no options */
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			mode = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_option = this_opt;
+	}
+	return mode;
+}
+#endif	/* MODULE */
+
+    /*
+     *  Initialisation
+     */
+
+static void ps3fb_platform_release(struct device *device)
+{
+	/* This is called when the reference count goes to zero. */
+}
+
+static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
+{
+	int error;
+
+	DPRINTK("version_driver:%x\n", dinfo->version_driver);
+	DPRINTK("irq outlet:%x\n", dinfo->irq.irq_outlet);
+	DPRINTK("version_gpu:%x memory_size:%x ch:%x core_freq:%d mem_freq:%d\n",
+		dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel,
+		dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);
+
+	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
+		printk(KERN_ERR "%s: version_driver err:%x\n", __FUNCTION__,
+		       dinfo->version_driver);
+		return -EINVAL;
+	}
+
+	ps3fb.dev = dev;
+	error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
+			      &ps3fb.irq_no);
+	if (error) {
+		printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
+		       error);
+		return error;
+	}
+
+	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
+			    "ps3fb vsync", ps3fb.dev);
+	if (error) {
+		printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
+		       error);
+		ps3_free_irq(ps3fb.irq_no);
+		return error;
+	}
+
+	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
+			  (1 << GPU_INTR_STATUS_FLIP_1);
+	return 0;
+}
+
+static int ps3fb_xdr_settings(u64 xdr_lpar)
+{
+	int status;
+
+	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
+				       xdr_lpar, ps3fb.videomemorysize, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n",
+		       __FUNCTION__, status);
+		return -ENXIO;
+	}
+	DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
+		ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar,
+		virt_to_abs(ps3fb.xdr_ea), ps3fb.videomemorysize);
+
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
+					   xdr_lpar, ps3fb.videomemorysize,
+					   GPU_IOIF, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
+		       __FUNCTION__, status);
+		return -ENXIO;
+	}
+	return 0;
+}
+
+static struct fb_ops ps3fb_ops = {
+	.fb_open	= ps3fb_open,
+	.fb_release	= ps3fb_release,
+	.fb_check_var	= ps3fb_check_var,
+	.fb_set_par	= ps3fb_set_par,
+	.fb_setcolreg	= ps3fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_mmap	= ps3fb_mmap,
+	.fb_blank	= ps3fb_blank,
+	.fb_ioctl	= ps3fb_ioctl,
+	.fb_compat_ioctl = ps3fb_ioctl
+};
+
+static struct fb_fix_screeninfo ps3fb_fix __initdata = {
+	.id =		"PS3 FB",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static int __init ps3fb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int retval = -ENOMEM;
+	u64 ddr_lpar = 0;
+	u64 lpar_dma_control = 0;
+	u64 lpar_driver_info = 0;
+	u64 lpar_reports = 0;
+	u64 lpar_reports_size = 0;
+	u64 xdr_lpar;
+	int status;
+	unsigned long offset;
+
+	/* get gpu context handle */
+	status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
+					 &ps3fb.memory_handle, &ddr_lpar);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n",
+		       __FUNCTION__, status);
+		goto err;
+	}
+	DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar);
+
+	status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
+					  &ps3fb.context_handle,
+					  &lpar_dma_control, &lpar_driver_info,
+					  &lpar_reports, &lpar_reports_size);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n",
+		       __FUNCTION__, status);
+		goto err_gpu_memory_free;
+	}
+
+	/* vsync interrupt */
+	ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);
+	if (!ps3fb.dinfo) {
+		printk(KERN_ERR "%s: ioremap failed\n", __FUNCTION__);
+		goto err_gpu_context_free;
+	}
+
+	retval = ps3fb_vsync_settings(ps3fb.dinfo, dev);
+	if (retval)
+		goto err_iounmap_dinfo;
+
+	/* xdr frame buffer */
+	ps3fb.xdr_ea = ps3fb_videomemory.address;
+	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea));
+	retval = ps3fb_xdr_settings(xdr_lpar);
+	if (retval)
+		goto err_free_irq;
+
+	ps3fb.videomemory_phys = virt_to_abs(ps3fb.xdr_ea);
+
+	/*
+	 * ps3fb must clear memory to prevent kernel info
+	 * leakage into userspace
+	 */
+	memset(ps3fb.xdr_ea, 0, ps3fb.videomemorysize);
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	if (!info)
+		goto err_free_irq;
+
+	offset = FB_OFF(ps3fb.res_index) + VP_OFF(ps3fb.res_index);
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+	info->fbops = &ps3fb_ops;
+
+	info->fix = ps3fb_fix;
+	info->fix.smem_start = ps3fb.videomemory_phys;
+	info->fix.smem_len = ps3fb.videomemorysize-offset;
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err_framebuffer_release;
+
+	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
+			  ARRAY_SIZE(ps3fb_modedb), ps3fb_default_mode(), 32)) {
+		retval = -EINVAL;
+		goto err_fb_dealloc;
+	}
+
+	fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb),
+				 &info->modelist);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_fb_dealloc;
+
+	platform_set_drvdata(dev, info);
+
+	printk(KERN_INFO
+	       "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
+	       info->node, ps3fb.videomemorysize >> 10);
+
+	kernel_thread(ps3fbd, info, CLONE_KERNEL);
+	return 0;
+
+err_fb_dealloc:
+	fb_dealloc_cmap(&info->cmap);
+err_framebuffer_release:
+	framebuffer_release(info);
+err_free_irq:
+	free_irq(ps3fb.irq_no, ps3fb.dev);
+	ps3_free_irq(ps3fb.irq_no);
+err_iounmap_dinfo:
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+err_gpu_context_free:
+	lv1_gpu_context_free(ps3fb.context_handle);
+err_gpu_memory_free:
+	lv1_gpu_memory_free(ps3fb.memory_handle);
+err:
+	return retval;
+}
+
+static int ps3fb_at_exit(struct notifier_block *self, unsigned long state,
+			 void *data)
+{
+	ps3fb_flip_ctl(0);	/* flip off */
+	ps3fb.dinfo->irq.mask = 0;
+	free_irq(ps3fb.irq_no, ps3fb.dev);
+	ps3_free_irq(ps3fb.irq_no);
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+	return NOTIFY_OK;
+}
+
+void ps3fb_cleanup(void)
+{
+	int status;
+
+	if (ps3fb.irq_no) {
+		free_irq(ps3fb.irq_no, ps3fb.dev);
+		ps3_free_irq(ps3fb.irq_no);
+	}
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+
+	status = lv1_gpu_context_free(ps3fb.context_handle);
+	if (status)
+		DPRINTK("lv1_gpu_context_free failed: %d\n", status);
+
+	status = lv1_gpu_memory_free(ps3fb.memory_handle);
+	if (status)
+		DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
+
+	ps3av_dev_close();
+}
+
+EXPORT_SYMBOL(ps3fb_cleanup);
+
+static int ps3fb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	ps3fb_cleanup();
+	return 0;
+}
+
+static struct platform_driver ps3fb_driver = {
+	.probe	= ps3fb_probe,
+	.remove = ps3fb_remove,
+	.driver = { .name = "ps3fb" }
+};
+
+static struct platform_device ps3fb_device = {
+	.name	= "ps3fb",
+	.id	= 0,
+	.dev	= { .release = ps3fb_platform_release }
+};
+
+static struct notifier_block ps3fb_reboot_nb = {
+	.notifier_call = ps3fb_at_exit
+};
+
+int ps3fb_set_sync(void)
+{
+	int status;
+
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
+		       __FUNCTION__, status);
+		return -1;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __FUNCTION__, status);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3fb_set_sync);
+
+static int __init ps3fb_init(void)
+{
+	int ret = 0;
+	int status;
+#ifndef MODULE
+	int mode;
+	char *option = NULL;
+
+	if (fb_get_options("ps3fb", &option))
+		goto err;
+#endif
+
+	if (!ps3fb_videomemory.address)
+		goto err;
+
+	status = ps3av_dev_open();
+	if (status) {
+		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__);
+		goto err;
+	}
+
+	/* set gpu-driver internal video mode */
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(0x0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET, 0, 0, 0, 0);	/* head a */
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __FUNCTION__, status);
+		goto err;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(0x0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET, 0, 0, 1, 0);	/* head b */
+
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __FUNCTION__, status);
+		goto err;
+	}
+#endif
+
+	ps3fb_mode = ps3av_get_mode();
+	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+#ifndef MODULE
+	mode = ps3fb_setup(option);	/* check boot option */
+	if (mode)
+		ps3fb_mode = mode;
+#endif
+	if (ps3fb_mode > 0) {
+		u32 xres, yres;
+		ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
+		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
+		DPRINTK("res_index:%d\n", ps3fb.res_index);
+	} else
+		ps3fb.res_index = GPU_RES_INDEX;
+	ps3fb.videomemorysize = ps3fb_videomemory.size;
+
+	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
+	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
+	init_MUTEX(&ps3fb.sem);
+	init_waitqueue_head(&ps3fb.wait_vsync);
+	ps3fb.num_frames = 1;
+	ret = platform_driver_register(&ps3fb_driver);
+
+	if (!ret) {
+		ret = platform_device_register(&ps3fb_device);
+		if (ret)
+			platform_driver_unregister(&ps3fb_driver);
+	}
+
+	register_reboot_notifier(&ps3fb_reboot_nb);
+	ps3fb_set_sync();
+
+	return ret;
+
+err:
+	return -ENXIO;
+}
+
+module_init(ps3fb_init);
+
+#ifdef MODULE
+static void __exit ps3fb_exit(void)
+{
+	platform_device_unregister(&ps3fb_device);
+	platform_driver_unregister(&ps3fb_driver);
+}
+
+module_exit(ps3fb_exit);
+
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
--- /dev/null
+++ ps3-linux/include/asm-powerpc/ps3fb.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _PS3FB_H_
+#define _PS3FB_H_
+
+/* ioctl */
+#define PS3FB_IOCTL_SETMODE       _IOW('r',  1, int) /* set video mode */
+#define PS3FB_IOCTL_GETMODE       _IOR('r',  2, int) /* get video mode */
+#define PS3FB_IOCTL_SCREENINFO    _IOR('r',  3, int) /* get screen info */
+#define PS3FB_IOCTL_ON            _IO('r', 4)        /* use IOCTL_FSEL */
+#define PS3FB_IOCTL_OFF           _IO('r', 5)        /* return to normal-flip */
+#define PS3FB_IOCTL_FSEL          _IOW('r', 6, int)  /* blit and flip request */
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC         _IOW('F', 0x20, __u32) /* wait for vsync */
+#endif
+
+struct ps3fb_ioctl_res {
+	__u32 xres; /* frame buffer x_size */
+	__u32 yres; /* frame buffer y_size */
+	__u32 xoff; /* margine x  */
+	__u32 yoff; /* margine y */
+	__u32 num_frames; /* num of frame buffers */
+};
+
+#endif /* _PS3FB_H_ */

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 6/9] ps3: Virtual Frame Buffer Driver
@ 2007-01-25 17:50   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:50 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

Add the PS3 Virtual Frame Buffer Driver.

As the actual graphics hardware cannot be accessed directly by Linux,
ps3fb uses a virtual frame buffer in main memory. The actual screen image is
copied to graphics memory by the GPU on every vertical blank, by making a
hypervisor call.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/video/Kconfig       |   19 
 drivers/video/Makefile      |    1 
 drivers/video/ps3fb.c       | 1266 ++++++++++++++++++++++++++++++++++++++++++++
 include/asm-powerpc/ps3fb.h |   42 +
 4 files changed, 1328 insertions(+)

--- ps3-linux.orig/drivers/video/Kconfig
+++ ps3-linux/drivers/video/Kconfig
@@ -1625,6 +1625,25 @@ config FB_IBM_GXT4500
 	  Say Y here to enable support for the IBM GXT4500P display
 	  adaptor, found on some IBM System P (pSeries) machines.
 
+config FB_PS3
+	bool "PS3 GPU framebuffer driver"
+	depends on FB && PS3_PS3AV=y
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Include support for the virtual frame buffer in the PS3 platform.
+
+config FB_PS3_DEFAULT_SIZE_M
+	int "PS3 default frame buffer size (in MiB)"
+	depends on FB_PS3
+	default 18
+	---help---
+	  This is the default size (in MiB) of the virtual frame buffer in
+	  the PS3.
+	  The default value can be overridden on the kernel command line
+	  using the "ps3fb" option (e.g. "ps3fb=9M");
+
 config FB_VIRTUAL
 	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
 	depends on FB
--- ps3-linux.orig/drivers/video/Makefile
+++ ps3-linux/drivers/video/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_FB_S3C2410)	  += s3c2410fb.
 obj-$(CONFIG_FB_PNX4008_DUM)	  += pnx4008/
 obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
 obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o
+obj-$(CONFIG_FB_PS3)		  += ps3fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
--- /dev/null
+++ ps3-linux/drivers/video/ps3fb.c
@@ -0,0 +1,1266 @@
+/*
+ * linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device
+ *
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ *  this file is based on :
+ *
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
+ *
+ *      Copyright (C) 2002 James Simmons
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/console.h>
+#include <linux/ioctl.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <asm/time.h>
+
+#include <asm/abs_addr.h>
+#include <asm/lv1call.h>
+#include <asm/ps3av.h>
+#include <asm/ps3fb.h>
+#include <asm/ps3.h>
+
+#ifdef PS3FB_DEBUG
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define PS3FB_DEV                                   0	/* /dev/fb0 */
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET    0x100
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC        0x101
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP        0x102
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP            0x600
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT             0x601
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT_SYNC        0x602
+
+#define L1GPU_DISPLAY_SYNC_HSYNC                    1
+#define L1GPU_DISPLAY_SYNC_VSYNC                    2
+
+#define DDR_SIZE                    (0)	/* used no ddr */
+#define GPU_OFFSET                  (64 * 1024)
+#define GPU_IOIF                    (0x0d000000UL)
+
+#define PS3FB_FULL_MODE_BIT         0x80
+
+#define GPU_INTR_STATUS_VSYNC_0     0	/* vsync on head A */
+#define GPU_INTR_STATUS_VSYNC_1     1	/* vsync on head B */
+#define GPU_INTR_STATUS_FLIP_0      3	/* flip head A */
+#define GPU_INTR_STATUS_FLIP_1      4	/* flip head B */
+#define GPU_INTR_STATUS_QUEUE_0     5	/* queue head A */
+#define GPU_INTR_STATUS_QUEUE_1     6	/* queue head B */
+
+#define GPU_DRIVER_INFO_VERSION     0x211
+
+/* gpu internals */
+struct display_head {
+	u64 be_time_stamp;
+	u32 status;
+	u32 offset;
+	u32 res1;
+	u32 res2;
+	u32 field;
+	u32 reserved1;
+
+	u64 res3;
+	u32 raster;
+
+	u64 vblank_count;
+	u32 field_vsync;
+	u32 reserved2;
+};
+
+struct gpu_irq {
+	u32 irq_outlet;
+	u32 status;
+	u32 mask;
+	u32 video_cause;
+	u32 graph_cause;
+	u32 user_cause;
+
+	u32 res1;
+	u64 res2;
+
+	u32 reserved[4];
+};
+
+struct gpu_driver_info {
+	u32 version_driver;
+	u32 version_gpu;
+	u32 memory_size;
+	u32 hardware_channel;
+
+	u32 nvcore_frequency;
+	u32 memory_frequency;
+
+	u32 reserved[1063];
+	struct display_head display_head[8];
+	struct gpu_irq irq;
+};
+
+struct ps3fb_priv {
+	unsigned long videomemory_phys;
+	unsigned long videomemorysize;
+	unsigned int irq_no;
+	void *dev;
+
+	u64 context_handle, memory_handle;
+	void *xdr_ea;
+	struct gpu_driver_info *dinfo;
+	struct semaphore sem;
+	u32 res_index;
+
+	u64 vblank_count;	/* frame count */
+	wait_queue_head_t wait_vsync;
+
+	u32 num_frames;		/* num of frame buffers */
+	atomic_t ext_flip;	/* on/off flip with vsync */
+	atomic_t f_count;	/* fb_open count */
+	int is_blanked;
+};
+static struct ps3fb_priv ps3fb;
+
+struct ps3fb_res_table {
+	u32 xres;
+	u32 yres;
+	u32 xoff;
+	u32 yoff;
+	u32 type;
+};
+#define PS3FB_RES_FULL 1
+static const struct ps3fb_res_table ps3fb_res[] = {
+	/* res_x,y   margin_x,y  full */
+	{  720,  480,  72,  48 , 0},
+	{  720,  576,  72,  58 , 0},
+	{ 1280,  720,  78,  38 , 0},
+	{ 1920, 1080, 116,  58 , 0},
+	/* full mode */
+	{  720,  480,   0,   0 , PS3FB_RES_FULL},
+	{  720,  576,   0,   0 , PS3FB_RES_FULL},
+	{ 1280,  720,   0,   0 , PS3FB_RES_FULL},
+	{ 1920, 1080,   0,   0 , PS3FB_RES_FULL},
+	/* vesa: normally full mode */
+	{ 1280,  768,   0,   0 , 0},
+	{ 1280, 1024,   0,   0 , 0},
+	{ 1920, 1200,   0,   0 , 0},
+	{    0,    0,   0,   0 , 0} };
+
+/* default resolution */
+#define GPU_RES_INDEX 0		/* 720 x 480 */
+
+static const struct fb_videomode ps3fb_modedb[] = {
+    /* 60 Hz broadcast modes (modes "1" to "5") */
+    {
+        /* 480i */
+        "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 480p */
+        "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080i */
+        "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (modes "6" to "10") */
+    {
+        /* 576i */
+        "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 576p */
+        "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080 */
+        "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* VESA modes (modes "11" to "13") */
+    {
+	/* WXGA */
+	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* SXGA */
+	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* WUXGA */
+	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
+	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    },
+
+    /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */
+    {
+	/* 480if */
+	"480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 480pf */
+	"480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */
+    {
+	/* 576if */
+	"576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 576pf */
+	"576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080f", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }
+};
+
+
+    /*
+     *  RAM we reserve for the frame buffer. This defines the maximum screen
+     *  size
+     *
+     *  The default can be overridden if the driver is compiled as a module
+     */
+
+#define HEAD_A
+#define HEAD_B
+
+#define X_OFF(i)	(ps3fb_res[i].xoff)	/* left/right margin (pixel) */
+#define Y_OFF(i)	(ps3fb_res[i].yoff)	/* top/bottom margin (pixel) */
+#define WIDTH(i)	(ps3fb_res[i].xres)	/* width of FB */
+#define HEIGHT(i)	(ps3fb_res[i].yres)	/* height of FB */
+#define BPP	4		/* number of bytes per pixel */
+#define VP_OFF(i)	(WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP)
+#define FB_OFF(i)	(GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
+
+static int ps3fb_mode = 0;
+module_param(ps3fb_mode, bool, 0);
+
+static char *mode_option __initdata = NULL;
+
+
+static int ps3fb_get_res_table(u32 xres, u32 yres)
+{
+	int i, full_mode;
+	u32 x, y, f = 0;
+
+	full_mode = (ps3fb_mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0;
+	for (i = 0;; i++) {
+		x = ps3fb_res[i].xres;
+		y = ps3fb_res[i].yres;
+		f = ps3fb_res[i].type;
+		if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL) {
+			continue;
+		}
+		if (x == 0) {
+			DPRINTK("ERROR: ps3fb_get_res_table()\n");
+			return -1;
+		}
+		if (x == xres && (yres == 0 || y == yres))
+			break;
+		x = x - 2 * ps3fb_res[i].xoff;
+		y = y - 2 * ps3fb_res[i].yoff;
+		if (x == xres && (yres == 0 || y == yres))
+			break;
+	}
+	return i;
+}
+
+static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,
+				    u32 *line_length)
+{
+	unsigned int i, mode;
+
+	for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++)
+		if (var->xres == ps3fb_modedb[i].xres &&
+		    var->yres == ps3fb_modedb[i].yres &&
+		    var->pixclock == ps3fb_modedb[i].pixclock &&
+		    var->hsync_len == ps3fb_modedb[i].hsync_len &&
+		    var->vsync_len == ps3fb_modedb[i].vsync_len &&
+		    var->left_margin == ps3fb_modedb[i].left_margin &&
+		    var->right_margin == ps3fb_modedb[i].right_margin &&
+		    var->upper_margin == ps3fb_modedb[i].upper_margin &&
+		    var->lower_margin == ps3fb_modedb[i].lower_margin &&
+		    var->sync == ps3fb_modedb[i].sync &&
+		    (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) {
+			/* Cropped broadcast modes use the full line_length */
+			*line_length =
+			    ps3fb_modedb[i < 10 ? i + 13 : i].xres * 4;
+			/* Full broadcast modes have the full mode bit set */
+			mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
+
+			DPRINTK("ps3fb_find_mode: mode %u\n", mode);
+			return mode;
+		}
+
+	DPRINTK("ps3fb_find_mode: mode not found\n");
+	return 0;
+
+}
+
+static const struct fb_videomode *ps3fb_default_mode(void)
+{
+	u32 mode = ps3fb_mode & PS3AV_MODE_MASK;
+	u32 flags = ps3fb_mode & ~PS3AV_MODE_MASK;
+
+	if (mode < 1 || mode > 13)
+		return NULL;
+
+	if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) {
+		/* Full broadcast mode */
+		return &ps3fb_modedb[mode + 12];
+	}
+
+	return &ps3fb_modedb[mode - 1];
+}
+
+static int ps3fb_sync(u32 frame)
+{
+	int i;
+	u32 xres, yres;
+	u64 head, fb_ioif, offset;
+	u64 sync = 1;
+	int status;
+
+	i = ps3fb.res_index;
+	xres = ps3fb_res[i].xres;
+	yres = ps3fb_res[i].yres;
+
+	if (frame > ps3fb.num_frames - 1) {
+		printk(KERN_WARNING "%s: invalid frame number (%u)\n",
+		       __FUNCTION__, frame);
+		return -EINVAL;
+	}
+	offset = xres * yres * BPP * frame;
+
+	fb_ioif = GPU_IOIF + FB_OFF(i) + offset;
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
+					   offset, fb_ioif,
+					   (sync << 32) | (xres << 16) | yres,
+					   xres * BPP);	/* line_length */
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
+		       __FUNCTION__, status);
+#ifdef HEAD_A
+	head = 0;
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
+					   head, offset, 0, 0);
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __FUNCTION__, status);
+#endif
+#ifdef HEAD_B
+	head = 1;
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
+					   head, offset, 0, 0);
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __FUNCTION__, status);
+#endif
+	return 0;
+}
+
+
+static int ps3fb_open(struct fb_info *info, int user)
+{
+	atomic_inc(&ps3fb.f_count);
+	return 0;
+}
+
+static int ps3fb_release(struct fb_info *info, int user)
+{
+	if (atomic_dec_and_test(&ps3fb.f_count)) {
+		if (atomic_read(&ps3fb.ext_flip)) {
+			atomic_set(&ps3fb.ext_flip, 0);
+			ps3fb_sync(0);	/* single buffer */
+		}
+	}
+	return 0;
+}
+
+    /*
+     *  Setting the video mode has been split into two parts.
+     *  First part, xxxfb_check_var, must not write anything
+     *  to hardware, it should only verify and adjust var.
+     *  This means it doesn't alter par but it does use hardware
+     *  data from it to check this var.
+     */
+
+static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u32 line_length;
+	int mode;
+	int i;
+
+	DPRINTK("var->xres:%u info->var.xres:%u\n", var->xres, info->var.xres);
+	DPRINTK("var->yres:%u info->var.yres:%u\n", var->yres, info->var.yres);
+
+	/* FIXME For now we do exact matches only */
+	mode = ps3fb_find_mode(var, &line_length);
+	if (!mode)
+		return -EINVAL;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/* Virtual screen and panning are not supported */
+	if (var->xres_virtual > var->xres || var->yres_virtual > var->yres ||
+	    var->xoffset || var->yoffset) {
+		DPRINTK("Virtual screen and panning are not supported\n");
+		return -EINVAL;
+	}
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	/* We support ARGB8888 only */
+	if (var->bits_per_pixel > 32 || var->grayscale ||
+	    var->red.offset > 16 || var->green.offset > 8 ||
+	    var->blue.offset > 0 || var->transp.offset > 24 ||
+	    var->red.length > 8 || var->green.length > 8 ||
+	    var->blue.length > 8 || var->transp.length > 8 ||
+	    var->red.msb_right || var->green.msb_right ||
+	    var->blue.msb_right || var->transp.msb_right || var->nonstd) {
+		DPRINTK("We support ARGB8888 only\n");
+		return -EINVAL;
+	}
+
+	var->bits_per_pixel = 32;
+	var->red.offset = 16;
+	var->green.offset = 8;
+	var->blue.offset = 0;
+	var->transp.offset = 24;
+	var->red.length = 8;
+	var->green.length = 8;
+	var->blue.length = 8;
+	var->transp.length = 8;
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	/* Rotation is not supported */
+	if (var->rotate) {
+		DPRINTK("Rotation is not supported\n");
+		return -EINVAL;
+	}
+
+	/* Memory limit */
+	i = ps3fb_get_res_table(var->xres, var->yres);
+	if (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP > ps3fb.videomemorysize) {
+		DPRINTK("Not enough memory\n");
+		return -ENOMEM;
+	}
+
+	var->height = -1;
+	var->width = -1;
+
+	return 0;
+}
+
+/* This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
+ */
+static int ps3fb_set_par(struct fb_info *info)
+{
+	unsigned int mode;
+	int i;
+	unsigned long offset;
+	static int first = 1;
+
+	DPRINTK("xres:%d xv:%d yres:%d yv:%d clock:%d\n",
+		info->var.xres, info->var.xres_virtual,
+		info->var.yres, info->var.yres_virtual, info->var.pixclock);
+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
+	ps3fb.res_index = i;
+
+	mode = ps3fb_find_mode(&info->var, &info->fix.line_length);
+	if (!mode)
+		return -EINVAL;
+
+	offset = FB_OFF(i) + VP_OFF(i);
+	info->fix.smem_len = ps3fb.videomemorysize-offset;
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+	memset(ps3fb.xdr_ea, 0, ps3fb.videomemorysize);
+
+	ps3fb.num_frames = ps3fb.videomemorysize/
+			   (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
+
+	/* Keep the special bits we cannot set using fb_var_screeninfo */
+	ps3fb_mode = (ps3fb_mode & ~PS3AV_MODE_MASK) | mode;
+
+	if (ps3av_set_video_mode(ps3fb_mode, first))
+		return -EINVAL;
+
+	first = 0;
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int ps3fb_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp, struct fb_info *info)
+{
+	if (regno >= 16)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	transp >>= 8;
+
+	((u32 *)info->pseudo_palette)[regno] = transp << 24 | red << 16 |
+					       green << 8 | blue;
+	return 0;
+}
+
+    /*
+     *  Most drivers don't need their own mmap function
+     */
+
+static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	int i;
+
+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
+	if (i == -1)
+		return -EINVAL;
+
+	if (offset + size > info->fix.smem_len)
+		return -EINVAL;
+	offset += ps3fb.videomemory_phys + FB_OFF(i) + VP_OFF(i);
+	if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
+			    size, vma->vm_page_prot))
+		return -EAGAIN;
+	printk(KERN_DEBUG "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", offset,
+	       vma->vm_start);
+	return 0;
+}
+
+    /*
+     * Blank the display
+     */
+
+static int ps3fb_blank(int blank, struct fb_info *info)
+{
+	int retval = 0;
+
+	DPRINTK("%s: blank:%d\n", __FUNCTION__, blank);
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		retval = ps3av_video_mute(1);	/* mute on */
+		if (!retval)
+			ps3fb.is_blanked = 1;
+		break;
+	default:		/* unblank */
+		retval = ps3av_video_mute(0);	/* mute off */
+		if (!retval)
+			ps3fb.is_blanked = 0;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fb_get_vblank(struct fb_vblank *vblank)
+{
+	memset(vblank, 0, sizeof(&vblank));
+	vblank->flags = FB_VBLANK_HAVE_VSYNC;
+	return 0;
+}
+
+int ps3fb_wait_for_vsync(u32 crtc)
+{
+	int ret;
+	u64 count;
+
+	count = ps3fb.vblank_count;
+	ret = wait_event_interruptible_timeout(ps3fb.wait_vsync,
+					       count != ps3fb.vblank_count,
+					       HZ / 10);
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3fb_wait_for_vsync);
+
+int ps3fb_flip_ctl(int on)
+{
+	if (on) {
+		if (atomic_read(&ps3fb.ext_flip) > 0) {
+			atomic_dec(&ps3fb.ext_flip);
+		}
+	} else {
+		atomic_inc(&ps3fb.ext_flip);
+	}
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3fb_flip_ctl);
+
+    /*
+     * ioctl
+     */
+
+static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	u32 val, old_mode;
+	int retval = 0;
+
+	switch (cmd) {
+	case FBIOGET_VBLANK:
+		{
+			struct fb_vblank vblank;
+			DPRINTK("FBIOGET_VBLANK:\n");
+			retval = ps3fb_get_vblank(&vblank);
+			if (!retval) {
+				if (copy_to_user(argp, &vblank,
+						 sizeof(vblank))) {
+					retval = -EFAULT;
+				}
+			}
+			break;
+		}
+
+	case FBIO_WAITFORVSYNC:
+		{
+			u32 crt;
+			DPRINTK("FBIO_WAITFORVSYNC:\n");
+			if (get_user(crt, (u32 __user *) arg)) {
+				retval = -EFAULT;
+				break;
+			}
+			retval = ps3fb_wait_for_vsync(crt);
+			break;
+		}
+
+	case PS3FB_IOCTL_SETMODE:
+		{
+			const struct fb_videomode *mode;
+			struct fb_var_screeninfo var;
+
+			if (copy_from_user(&val, argp, sizeof(val))) {
+				retval = -EFAULT;
+				break;
+			}
+			DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
+			retval = -EINVAL;
+			old_mode = ps3fb_mode;
+			ps3fb_mode = val;
+			mode = ps3fb_default_mode();
+			if (mode) {
+				var = info->var;
+				fb_videomode_to_var(&var, mode);
+				acquire_console_sem();
+				info->flags |= FBINFO_MISC_USEREVENT;
+				/* Force, in case only special bits changed */
+				var.activate |= FB_ACTIVATE_FORCE;
+				retval = fb_set_var(info, &var);
+				info->flags &= ~FBINFO_MISC_USEREVENT;
+				release_console_sem();
+			}
+			if (retval)
+				ps3fb_mode = old_mode;
+			break;
+		}
+
+	case PS3FB_IOCTL_GETMODE:
+		val = ps3av_get_mode();
+		DPRINTK("PS3FB_IOCTL_GETMODE:%x\n", val);
+		if (copy_to_user(argp, &val, sizeof(val))) {
+			retval = -EFAULT;
+		}
+		break;
+
+	case PS3FB_IOCTL_SCREENINFO:
+		{
+			struct ps3fb_ioctl_res res;
+			int i = ps3fb.res_index;
+			DPRINTK("PS3FB_IOCTL_SCREENINFO:\n");
+			res.xres = ps3fb_res[i].xres;
+			res.yres = ps3fb_res[i].yres;
+			res.xoff = ps3fb_res[i].xoff;
+			res.yoff = ps3fb_res[i].yoff;
+			res.num_frames = ps3fb.num_frames;
+			if (copy_to_user(argp, &res, sizeof(res))) {
+				retval = -EFAULT;
+			}
+			break;
+		}
+
+	case PS3FB_IOCTL_ON:
+		DPRINTK("PS3FB_IOCTL_ON:\n");
+		atomic_inc(&ps3fb.ext_flip);
+		break;
+
+	case PS3FB_IOCTL_OFF:
+		DPRINTK("PS3FB_IOCTL_OFF:\n");
+		if (atomic_read(&ps3fb.ext_flip) > 0) {
+			atomic_dec(&ps3fb.ext_flip);
+		}
+		break;
+
+	case PS3FB_IOCTL_FSEL:
+		if (copy_from_user(&val, argp, sizeof(val))) {
+			retval = -EFAULT;
+			break;
+		}
+		DPRINTK("PS3FB_IOCTL_FSEL:%d\n", val);
+		retval = ps3fb_sync(val);
+		break;
+
+	default:
+		retval = -ENOTTY;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fbd(void *arg)
+{
+	daemonize("ps3fbd");
+	for (;;) {
+		down(&ps3fb.sem);
+		if (atomic_read(&ps3fb.ext_flip) == 0)
+			ps3fb_sync(0);	/* single buffer */
+	}
+	return 0;
+}
+
+static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
+{
+	u64 v1;
+	int status;
+	struct display_head *head = &ps3fb.dinfo->display_head[1];
+
+	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n",
+		       __FUNCTION__, status);
+		return IRQ_NONE;
+	}
+
+	if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
+		/* VSYNC */
+		ps3fb.vblank_count = head->vblank_count;
+		if (!ps3fb.is_blanked)
+			up(&ps3fb.sem);
+		wake_up_interruptible(&ps3fb.wait_vsync);
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifndef MODULE
+static int __init ps3fb_setup(char *options)
+{
+	char *this_opt;
+	int mode = 0;
+
+	if (!options || !*options)
+		return 0;	/* no options */
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			mode = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_option = this_opt;
+	}
+	return mode;
+}
+#endif	/* MODULE */
+
+    /*
+     *  Initialisation
+     */
+
+static void ps3fb_platform_release(struct device *device)
+{
+	/* This is called when the reference count goes to zero. */
+}
+
+static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
+{
+	int error;
+
+	DPRINTK("version_driver:%x\n", dinfo->version_driver);
+	DPRINTK("irq outlet:%x\n", dinfo->irq.irq_outlet);
+	DPRINTK("version_gpu:%x memory_size:%x ch:%x core_freq:%d mem_freq:%d\n",
+		dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel,
+		dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);
+
+	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
+		printk(KERN_ERR "%s: version_driver err:%x\n", __FUNCTION__,
+		       dinfo->version_driver);
+		return -EINVAL;
+	}
+
+	ps3fb.dev = dev;
+	error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
+			      &ps3fb.irq_no);
+	if (error) {
+		printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
+		       error);
+		return error;
+	}
+
+	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
+			    "ps3fb vsync", ps3fb.dev);
+	if (error) {
+		printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
+		       error);
+		ps3_free_irq(ps3fb.irq_no);
+		return error;
+	}
+
+	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
+			  (1 << GPU_INTR_STATUS_FLIP_1);
+	return 0;
+}
+
+static int ps3fb_xdr_settings(u64 xdr_lpar)
+{
+	int status;
+
+	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
+				       xdr_lpar, ps3fb.videomemorysize, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n",
+		       __FUNCTION__, status);
+		return -ENXIO;
+	}
+	DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
+		ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar,
+		virt_to_abs(ps3fb.xdr_ea), ps3fb.videomemorysize);
+
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
+					   xdr_lpar, ps3fb.videomemorysize,
+					   GPU_IOIF, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
+		       __FUNCTION__, status);
+		return -ENXIO;
+	}
+	return 0;
+}
+
+static struct fb_ops ps3fb_ops = {
+	.fb_open	= ps3fb_open,
+	.fb_release	= ps3fb_release,
+	.fb_check_var	= ps3fb_check_var,
+	.fb_set_par	= ps3fb_set_par,
+	.fb_setcolreg	= ps3fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_mmap	= ps3fb_mmap,
+	.fb_blank	= ps3fb_blank,
+	.fb_ioctl	= ps3fb_ioctl,
+	.fb_compat_ioctl = ps3fb_ioctl
+};
+
+static struct fb_fix_screeninfo ps3fb_fix __initdata = {
+	.id =		"PS3 FB",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static int __init ps3fb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int retval = -ENOMEM;
+	u64 ddr_lpar = 0;
+	u64 lpar_dma_control = 0;
+	u64 lpar_driver_info = 0;
+	u64 lpar_reports = 0;
+	u64 lpar_reports_size = 0;
+	u64 xdr_lpar;
+	int status;
+	unsigned long offset;
+
+	/* get gpu context handle */
+	status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
+					 &ps3fb.memory_handle, &ddr_lpar);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n",
+		       __FUNCTION__, status);
+		goto err;
+	}
+	DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar);
+
+	status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
+					  &ps3fb.context_handle,
+					  &lpar_dma_control, &lpar_driver_info,
+					  &lpar_reports, &lpar_reports_size);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n",
+		       __FUNCTION__, status);
+		goto err_gpu_memory_free;
+	}
+
+	/* vsync interrupt */
+	ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);
+	if (!ps3fb.dinfo) {
+		printk(KERN_ERR "%s: ioremap failed\n", __FUNCTION__);
+		goto err_gpu_context_free;
+	}
+
+	retval = ps3fb_vsync_settings(ps3fb.dinfo, dev);
+	if (retval)
+		goto err_iounmap_dinfo;
+
+	/* xdr frame buffer */
+	ps3fb.xdr_ea = ps3fb_videomemory.address;
+	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea));
+	retval = ps3fb_xdr_settings(xdr_lpar);
+	if (retval)
+		goto err_free_irq;
+
+	ps3fb.videomemory_phys = virt_to_abs(ps3fb.xdr_ea);
+
+	/*
+	 * ps3fb must clear memory to prevent kernel info
+	 * leakage into userspace
+	 */
+	memset(ps3fb.xdr_ea, 0, ps3fb.videomemorysize);
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	if (!info)
+		goto err_free_irq;
+
+	offset = FB_OFF(ps3fb.res_index) + VP_OFF(ps3fb.res_index);
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+	info->fbops = &ps3fb_ops;
+
+	info->fix = ps3fb_fix;
+	info->fix.smem_start = ps3fb.videomemory_phys;
+	info->fix.smem_len = ps3fb.videomemorysize-offset;
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err_framebuffer_release;
+
+	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
+			  ARRAY_SIZE(ps3fb_modedb), ps3fb_default_mode(), 32)) {
+		retval = -EINVAL;
+		goto err_fb_dealloc;
+	}
+
+	fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb),
+				 &info->modelist);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_fb_dealloc;
+
+	platform_set_drvdata(dev, info);
+
+	printk(KERN_INFO
+	       "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
+	       info->node, ps3fb.videomemorysize >> 10);
+
+	kernel_thread(ps3fbd, info, CLONE_KERNEL);
+	return 0;
+
+err_fb_dealloc:
+	fb_dealloc_cmap(&info->cmap);
+err_framebuffer_release:
+	framebuffer_release(info);
+err_free_irq:
+	free_irq(ps3fb.irq_no, ps3fb.dev);
+	ps3_free_irq(ps3fb.irq_no);
+err_iounmap_dinfo:
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+err_gpu_context_free:
+	lv1_gpu_context_free(ps3fb.context_handle);
+err_gpu_memory_free:
+	lv1_gpu_memory_free(ps3fb.memory_handle);
+err:
+	return retval;
+}
+
+static int ps3fb_at_exit(struct notifier_block *self, unsigned long state,
+			 void *data)
+{
+	ps3fb_flip_ctl(0);	/* flip off */
+	ps3fb.dinfo->irq.mask = 0;
+	free_irq(ps3fb.irq_no, ps3fb.dev);
+	ps3_free_irq(ps3fb.irq_no);
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+	return NOTIFY_OK;
+}
+
+void ps3fb_cleanup(void)
+{
+	int status;
+
+	if (ps3fb.irq_no) {
+		free_irq(ps3fb.irq_no, ps3fb.dev);
+		ps3_free_irq(ps3fb.irq_no);
+	}
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+
+	status = lv1_gpu_context_free(ps3fb.context_handle);
+	if (status)
+		DPRINTK("lv1_gpu_context_free failed: %d\n", status);
+
+	status = lv1_gpu_memory_free(ps3fb.memory_handle);
+	if (status)
+		DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
+
+	ps3av_dev_close();
+}
+
+EXPORT_SYMBOL(ps3fb_cleanup);
+
+static int ps3fb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	ps3fb_cleanup();
+	return 0;
+}
+
+static struct platform_driver ps3fb_driver = {
+	.probe	= ps3fb_probe,
+	.remove = ps3fb_remove,
+	.driver = { .name = "ps3fb" }
+};
+
+static struct platform_device ps3fb_device = {
+	.name	= "ps3fb",
+	.id	= 0,
+	.dev	= { .release = ps3fb_platform_release }
+};
+
+static struct notifier_block ps3fb_reboot_nb = {
+	.notifier_call = ps3fb_at_exit
+};
+
+int ps3fb_set_sync(void)
+{
+	int status;
+
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
+		       __FUNCTION__, status);
+		return -1;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __FUNCTION__, status);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+EXPORT_SYMBOL(ps3fb_set_sync);
+
+static int __init ps3fb_init(void)
+{
+	int ret = 0;
+	int status;
+#ifndef MODULE
+	int mode;
+	char *option = NULL;
+
+	if (fb_get_options("ps3fb", &option))
+		goto err;
+#endif
+
+	if (!ps3fb_videomemory.address)
+		goto err;
+
+	status = ps3av_dev_open();
+	if (status) {
+		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__);
+		goto err;
+	}
+
+	/* set gpu-driver internal video mode */
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(0x0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET, 0, 0, 0, 0);	/* head a */
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __FUNCTION__, status);
+		goto err;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(0x0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET, 0, 0, 1, 0);	/* head b */
+
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __FUNCTION__, status);
+		goto err;
+	}
+#endif
+
+	ps3fb_mode = ps3av_get_mode();
+	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+#ifndef MODULE
+	mode = ps3fb_setup(option);	/* check boot option */
+	if (mode)
+		ps3fb_mode = mode;
+#endif
+	if (ps3fb_mode > 0) {
+		u32 xres, yres;
+		ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
+		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
+		DPRINTK("res_index:%d\n", ps3fb.res_index);
+	} else
+		ps3fb.res_index = GPU_RES_INDEX;
+	ps3fb.videomemorysize = ps3fb_videomemory.size;
+
+	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
+	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
+	init_MUTEX(&ps3fb.sem);
+	init_waitqueue_head(&ps3fb.wait_vsync);
+	ps3fb.num_frames = 1;
+	ret = platform_driver_register(&ps3fb_driver);
+
+	if (!ret) {
+		ret = platform_device_register(&ps3fb_device);
+		if (ret)
+			platform_driver_unregister(&ps3fb_driver);
+	}
+
+	register_reboot_notifier(&ps3fb_reboot_nb);
+	ps3fb_set_sync();
+
+	return ret;
+
+err:
+	return -ENXIO;
+}
+
+module_init(ps3fb_init);
+
+#ifdef MODULE
+static void __exit ps3fb_exit(void)
+{
+	platform_device_unregister(&ps3fb_device);
+	platform_driver_unregister(&ps3fb_driver);
+}
+
+module_exit(ps3fb_exit);
+
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
--- /dev/null
+++ ps3-linux/include/asm-powerpc/ps3fb.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright (C) 2006-2007 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _PS3FB_H_
+#define _PS3FB_H_
+
+/* ioctl */
+#define PS3FB_IOCTL_SETMODE       _IOW('r',  1, int) /* set video mode */
+#define PS3FB_IOCTL_GETMODE       _IOR('r',  2, int) /* get video mode */
+#define PS3FB_IOCTL_SCREENINFO    _IOR('r',  3, int) /* get screen info */
+#define PS3FB_IOCTL_ON            _IO('r', 4)        /* use IOCTL_FSEL */
+#define PS3FB_IOCTL_OFF           _IO('r', 5)        /* return to normal-flip */
+#define PS3FB_IOCTL_FSEL          _IOW('r', 6, int)  /* blit and flip request */
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC         _IOW('F', 0x20, __u32) /* wait for vsync */
+#endif
+
+struct ps3fb_ioctl_res {
+	__u32 xres; /* frame buffer x_size */
+	__u32 yres; /* frame buffer y_size */
+	__u32 xoff; /* margine x  */
+	__u32 yoff; /* margine y */
+	__u32 num_frames; /* num of frame buffers */
+};
+
+#endif /* _PS3FB_H_ */

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 7/9] ps3: disable display flipping during mode changes
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:51   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:51 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

If ps3fb is available, we have to disable display flipping while changing the
audio or video mode.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/ps3/ps3av_cmd.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletion(-)

--- ps3-linux.orig/drivers/ps3/ps3av_cmd.c
+++ ps3-linux/drivers/ps3/ps3av_cmd.c
@@ -33,6 +33,12 @@
 #define DPRINTK(fmt, args...) do { } while (0)
 #endif
 
+#ifdef CONFIG_FB_PS3
+extern int ps3fb_flip_ctl(int);
+#else
+#define ps3fb_flip_ctl(x)
+#endif
+
 static const struct video_fmt {
 	u32 format;
 	u32 order;
@@ -884,8 +890,9 @@ int ps3av_cmd_avb_param(struct ps3av_pkt
 {
 	int res;
 
-	/* avb packet */
+	ps3fb_flip_ctl(0);	/* flip off */
 
+	/* avb packet */
 	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
 			   &avb->send_hdr);
 	if (res < 0)
@@ -896,6 +903,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt
 		DPRINTK("PS3AV_CID_AVB_PARAM: failed %x\n", res);
 
       out:
+	ps3fb_flip_ctl(1);	/* flip on */
 	return res;
 }
 

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 7/9] ps3: disable display flipping during mode changes
@ 2007-01-25 17:51   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:51 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

If ps3fb is available, we have to disable display flipping while changing the
audio or video mode.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 drivers/ps3/ps3av_cmd.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletion(-)

--- ps3-linux.orig/drivers/ps3/ps3av_cmd.c
+++ ps3-linux/drivers/ps3/ps3av_cmd.c
@@ -33,6 +33,12 @@
 #define DPRINTK(fmt, args...) do { } while (0)
 #endif
 
+#ifdef CONFIG_FB_PS3
+extern int ps3fb_flip_ctl(int);
+#else
+#define ps3fb_flip_ctl(x)
+#endif
+
 static const struct video_fmt {
 	u32 format;
 	u32 order;
@@ -884,8 +890,9 @@ int ps3av_cmd_avb_param(struct ps3av_pkt
 {
 	int res;
 
-	/* avb packet */
+	ps3fb_flip_ctl(0);	/* flip off */
 
+	/* avb packet */
 	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
 			   &avb->send_hdr);
 	if (res < 0)
@@ -896,6 +903,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt
 		DPRINTK("PS3AV_CID_AVB_PARAM: failed %x\n", res);
 
       out:
+	ps3fb_flip_ctl(1);	/* flip on */
 	return res;
 }
 

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:51   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:51 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

PS3: Cleanup the frame buffer device before clearing the HPTE mapping

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 arch/powerpc/platforms/ps3/htab.c |    5 +++++
 1 files changed, 5 insertions(+)

--- ps3-linux.orig/arch/powerpc/platforms/ps3/htab.c
+++ ps3-linux/arch/powerpc/platforms/ps3/htab.c
@@ -234,6 +234,11 @@ static void ps3_hpte_invalidate(unsigned
 
 static void ps3_hpte_clear(void)
 {
+	extern void ps3fb_cleanup(void);
+
+#ifdef CONFIG_FB_PS3
+	ps3fb_cleanup();
+#endif
 	lv1_unmap_htab(htab_addr);
 }
 

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
@ 2007-01-25 17:51   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:51 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

PS3: Cleanup the frame buffer device before clearing the HPTE mapping

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 arch/powerpc/platforms/ps3/htab.c |    5 +++++
 1 files changed, 5 insertions(+)

--- ps3-linux.orig/arch/powerpc/platforms/ps3/htab.c
+++ ps3-linux/arch/powerpc/platforms/ps3/htab.c
@@ -234,6 +234,11 @@ static void ps3_hpte_invalidate(unsigned
 
 static void ps3_hpte_clear(void)
 {
+	extern void ps3fb_cleanup(void);
+
+#ifdef CONFIG_FB_PS3
+	ps3fb_cleanup();
+#endif
 	lv1_unmap_htab(htab_addr);
 }
 

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 9/9] ps3: ps3av/fb defconfig updates
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:52   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:52 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

PS3: defconfig updates for ps3av and ps3fb

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 arch/powerpc/configs/ps3_defconfig |   29 ++++++++++++++++++++++++++++-
 1 files changed, 28 insertions(+), 1 deletion(-)

--- ps3-linux.orig/arch/powerpc/configs/ps3_defconfig
+++ ps3-linux/arch/powerpc/configs/ps3_defconfig
@@ -163,6 +163,7 @@ CONFIG_PS3_HTAB_SIZE=20
 CONFIG_PS3_DYNAMIC_DMA=y
 CONFIG_PS3_USE_LPAR_ADDR=y
 CONFIG_PS3_VUART=y
+CONFIG_PS3_PS3AV=y
 
 #
 # Kernel options
@@ -605,14 +606,40 @@ CONFIG_GEN_RTC=y
 # Graphics support
 #
 # CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_PS3=y
+CONFIG_FB_PS3_DEFAULT_SIZE_M=18
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 9/9] ps3: ps3av/fb defconfig updates
@ 2007-01-25 17:52   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:52 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development

PS3: defconfig updates for ps3av and ps3fb

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
 arch/powerpc/configs/ps3_defconfig |   29 ++++++++++++++++++++++++++++-
 1 files changed, 28 insertions(+), 1 deletion(-)

--- ps3-linux.orig/arch/powerpc/configs/ps3_defconfig
+++ ps3-linux/arch/powerpc/configs/ps3_defconfig
@@ -163,6 +163,7 @@ CONFIG_PS3_HTAB_SIZE=20
 CONFIG_PS3_DYNAMIC_DMA=y
 CONFIG_PS3_USE_LPAR_ADDR=y
 CONFIG_PS3_VUART=y
+CONFIG_PS3_PS3AV=y
 
 #
 # Kernel options
@@ -605,14 +606,40 @@ CONFIG_GEN_RTC=y
 # Graphics support
 #
 # CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_PS3=y
+CONFIG_FB_PS3_DEFAULT_SIZE_M=18
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 0/9] ps3av/fb drivers for 2.6.21
  2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
@ 2007-01-25 17:55   ` Geert Uytterhoeven
  2007-01-25 17:48   ` Geert Uytterhoeven
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:55 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development


Sorry, I forgot to mention that the following 3 patches are not really
PS3-specific:

> [PATCH 2/9] fbdev modedb: allow refresh rates for named video modes

Without this you cannot select all available video modes through the kernel
command line.

> [PATCH 3/9] fbdev modedb: make more pointer parameters const

Just a cleanup while working on the code.

> [PATCH 4/9] fb_videomode_to_var: reset virtual screen parameters

Without this you cannot use the ps3videomode command line tool or
/sys/class/graphics/fb0/mode to switch to a video mode with a lower resolution.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 0/9] ps3av/fb drivers for 2.6.21
@ 2007-01-25 17:55   ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-25 17:55 UTC (permalink / raw)
  To: James Simmons, Paul Mackerras
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development


Sorry, I forgot to mention that the following 3 patches are not really
PS3-specific:

> [PATCH 2/9] fbdev modedb: allow refresh rates for named video modes

Without this you cannot select all available video modes through the kernel
command line.

> [PATCH 3/9] fbdev modedb: make more pointer parameters const

Just a cleanup while working on the code.

> [PATCH 4/9] fb_videomode_to_var: reset virtual screen parameters

Without this you cannot use the ps3videomode command line tool or
/sys/class/graphics/fb0/mode to switch to a video mode with a lower resolution.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [Linux-fbdev-devel] [PATCH 6/9] ps3: Virtual Frame Buffer Driver
  2007-01-25 17:50   ` Geert Uytterhoeven
  (?)
@ 2007-01-25 21:36   ` Bernhard Fischer
  -1 siblings, 0 replies; 64+ messages in thread
From: Bernhard Fischer @ 2007-01-25 21:36 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux/PPC Development, Linux Frame Buffer Device Development,
	Paul Mackerras, Bernhard Fischer

Just some minor cosmetics..

On Thu, Jan 25, 2007 at 06:50:44PM +0100, Geert Uytterhoeven wrote:
>--- /dev/null
>+++ ps3-linux/drivers/video/ps3fb.c
>@@ -0,0 +1,1266 @@
>+/*
>+ * linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device
>+ *
>+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
>+ * Copyright (C) 2006-2007 Sony Corporation
>+ *
>+ *  this file is based on :
>+ *
>+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
>+ *
>+ *      Copyright (C) 2002 James Simmons
>+ *
>+ *	Copyright (C) 1997 Geert Uytterhoeven

One (C) has spaces, yours a tab.


>+struct ps3fb_priv {
>+	unsigned long videomemory_phys;
>+	unsigned long videomemorysize;

Is the naming with and without underscore intentional?


>+static int ps3fb_get_res_table(u32 xres, u32 yres)
>+{
>+	int i, full_mode;

unsigned?

>+	u32 x, y, f = 0;
>+
>+	full_mode = (ps3fb_mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0;
>+	for (i = 0;; i++) {
>+		x = ps3fb_res[i].xres;
>+		y = ps3fb_res[i].yres;
>+		f = ps3fb_res[i].type;

Why did you set f=0 above?

>+
>+static const struct fb_videomode *ps3fb_default_mode(void)
>+{
>+	u32 mode = ps3fb_mode & PS3AV_MODE_MASK;
>+	u32 flags = ps3fb_mode & ~PS3AV_MODE_MASK;
>+
>+	if (mode < 1 || mode > 13)
>+		return NULL;

smaller if you set flags only after this check?


>+static int ps3fb_sync(u32 frame)
>+{
>+	int i;
>+	u32 xres, yres;
>+	u64 head, fb_ioif, offset;

#if defined HEAD_A || defined HEAD_B
	u64 head;
#endif

Resp, remove it and pass the value in directly like you do in
ps3fb_set_sync()?

It's unlikely that neither HEAD_A nor HEAD_B are defined, i assume, so
the check is most likely not needed?

>+	u64 sync = 1;

you don't seem to use sync much, perhaps use just 1 below?

>+	int status;

I'd reuse status and drop i, perhaps.
>+
>+	i = ps3fb.res_index;
>+	xres = ps3fb_res[i].xres;
>+	yres = ps3fb_res[i].yres;
>+
>+	if (frame > ps3fb.num_frames - 1) {
>+		printk(KERN_WARNING "%s: invalid frame number (%u)\n",
>+		       __FUNCTION__, frame);
>+		return -EINVAL;
>+	}
>+	offset = xres * yres * BPP * frame;
>+
>+	fb_ioif = GPU_IOIF + FB_OFF(i) + offset;
>+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
>+					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
>+					   offset, fb_ioif,
>+					   (sync << 32) | (xres << 16) | yres,
>+					   xres * BPP);	/* line_length */
>+	if (status)
>+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
>+		       __FUNCTION__, status);
>+#ifdef HEAD_A
>+	head = 0;
>+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
>+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
>+					   head, offset, 0, 0);
>+	if (status)
>+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
>+		       __FUNCTION__, status);
>+#endif
>+#ifdef HEAD_B
>+	head = 1;
>+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
>+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
>+					   head, offset, 0, 0);
>+	if (status)
>+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
>+		       __FUNCTION__, status);
>+#endif
>+	return 0;
>+}


[snip ps3fb_check_var that doesn't need a mode variable currently so i'd
drop it]

>+/* This routine actually sets the video mode. It's in here where we
>+ * the hardware state info->par and fix which can be affected by the
>+ * change in par. For this driver it doesn't do much.
>+ */

I can't parse the second sentence, something is missing..

>+static int ps3fb_set_par(struct fb_info *info)
>+{
>+	unsigned int mode;
>+	int i;
>+	unsigned long offset;
>+	static int first = 1;
>+
>+	DPRINTK("xres:%d xv:%d yres:%d yv:%d clock:%d\n",
>+		info->var.xres, info->var.xres_virtual,
>+		info->var.yres, info->var.yres_virtual, info->var.pixclock);
>+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
>+	ps3fb.res_index = i;
>+
>+	mode = ps3fb_find_mode(&info->var, &info->fix.line_length);
>+	if (!mode)
>+		return -EINVAL;
>+
>+	offset = FB_OFF(i) + VP_OFF(i);
>+	info->fix.smem_len = ps3fb.videomemorysize-offset;

spaces around the minus would make this more readable

>+	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
>+	memset(ps3fb.xdr_ea, 0, ps3fb.videomemorysize);
>+
>+	ps3fb.num_frames = ps3fb.videomemorysize/
>+			   (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
>+
>+	/* Keep the special bits we cannot set using fb_var_screeninfo */
>+	ps3fb_mode = (ps3fb_mode & ~PS3AV_MODE_MASK) | mode;
>+
>+	if (ps3av_set_video_mode(ps3fb_mode, first))
>+		return -EINVAL;
>+
>+	first = 0;
>+	return 0;
>+}

>+    /*
>+     *  Most drivers don't need their own mmap function
>+     */

hm?

>+
>+static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
>+{
>+	unsigned long size = vma->vm_end - vma->vm_start;
>+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;

>+	int i;
>+
>+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
>+	if (i == -1)
>+		return -EINVAL;

	unsigned long size, offset;

	if (ps3fb_get_res_table(info->var.xres, info->var.yres) == -1)
		return -EINVAL;
	
	size = vma->vm_end - vma->vm_start;
	offset = vma->vm_pgoff << PAGE_SHIFT;

perhaps ?
>+
>+	if (offset + size > info->fix.smem_len)
>+		return -EINVAL;
>+	offset += ps3fb.videomemory_phys + FB_OFF(i) + VP_OFF(i);
>+	if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
>+			    size, vma->vm_page_prot))
>+		return -EAGAIN;
>+	printk(KERN_DEBUG "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", offset,
>+	       vma->vm_start);
>+	return 0;
>+}
>+
>+    /*
>+     * Blank the display
>+     */
>+
>+static int ps3fb_blank(int blank, struct fb_info *info)
>+{
>+	int retval = 0;

Not sure why you set the retval here while ps3av_set_av_video_mute seem
to allways return 0 or -1 and retval will always be set below?

>+	DPRINTK("%s: blank:%d\n", __FUNCTION__, blank);
>+	switch (blank) {
>+	case FB_BLANK_POWERDOWN:
>+	case FB_BLANK_HSYNC_SUSPEND:
>+	case FB_BLANK_VSYNC_SUSPEND:
>+	case FB_BLANK_NORMAL:
>+		retval = ps3av_video_mute(1);	/* mute on */
>+		if (!retval)
>+			ps3fb.is_blanked = 1;
>+		break;
>+	default:		/* unblank */
>+		retval = ps3av_video_mute(0);	/* mute off */
>+		if (!retval)
>+			ps3fb.is_blanked = 0;
>+		break;
>+	}
>+	return retval;
>+}


>+int ps3fb_wait_for_vsync(u32 crtc)
>+{
->+	int ret;
>+	u64 count;
>+
>+	count = ps3fb.vblank_count;
>+	ret = wait_event_interruptible_timeout(ps3fb.wait_vsync,
>+					       count != ps3fb.vblank_count,
>+					       HZ / 10);
>+	if (!ret)
>+		return -ETIMEDOUT;
>+
>+	return 0;
>+}
>+
>+EXPORT_SYMBOL(ps3fb_wait_for_vsync);
>+

>+int ps3fb_flip_ctl(int on)

void?

>+{
>+	if (on) {
>+		if (atomic_read(&ps3fb.ext_flip) > 0) {
>+			atomic_dec(&ps3fb.ext_flip);
>+		}
>+	} else {
>+		atomic_inc(&ps3fb.ext_flip);
>+	}
>+	return 0;
>+}
>+
>+EXPORT_SYMBOL(ps3fb_flip_ctl);
>+
>+    /*
>+     * ioctl
>+     */
>+
>+static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
>+		       unsigned long arg)
>+{
>+	void __user *argp = (void __user *)arg;
>+	u32 val, old_mode;
>+	int retval = 0;
>+
>+	switch (cmd) {
>+	case FBIOGET_VBLANK:
>+		{
>+			struct fb_vblank vblank;
>+			DPRINTK("FBIOGET_VBLANK:\n");
>+			retval = ps3fb_get_vblank(&vblank);
>+			if (!retval) {
>+				if (copy_to_user(argp, &vblank,
>+						 sizeof(vblank))) {
>+					retval = -EFAULT;
>+				}
>+			}
>+			break;
>+		}
>+
>+	case FBIO_WAITFORVSYNC:
>+		{
>+			u32 crt;
>+			DPRINTK("FBIO_WAITFORVSYNC:\n");
>+			if (get_user(crt, (u32 __user *) arg)) {
>+				retval = -EFAULT;
>+				break;
>+			}
>+			retval = ps3fb_wait_for_vsync(crt);
>+			break;
>+		}
>+
>+	case PS3FB_IOCTL_SETMODE:
>+		{
>+			const struct fb_videomode *mode;
>+			struct fb_var_screeninfo var;
>+
>+			if (copy_from_user(&val, argp, sizeof(val))) {
>+				retval = -EFAULT;
>+				break;
>+			}
>+			DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
>+			retval = -EINVAL;

I'd default to -EFAULT and eventually set retval = 0 if !copy_from and if
all went fine (like for get_mode) but that's probably not the convention.
Didn't look recently.


>+static int __init ps3fb_init(void)
>+{
>+	int ret = 0;

ret is set here and then again set by platform_driver_register() but not
used for anything else until then. s/= 0//

>+	int status;
>+#ifndef MODULE
>+	int mode;
>+	char *option = NULL;
>+
>+	if (fb_get_options("ps3fb", &option))
>+		goto err;
>+#endif
>+
>+	if (!ps3fb_videomemory.address)
>+		goto err;
>+
>+	status = ps3av_dev_open();
>+	if (status) {
>+		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__);
>+		goto err;
>+	}
>+
>+	/* set gpu-driver internal video mode */
>+#ifdef HEAD_A
>+	status = lv1_gpu_context_attribute(0x0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET, 0, 0, 0, 0);	/* head a */
>+	if (status) {
>+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
>+		       __FUNCTION__, status);
>+		goto err;
>+	}
>+#endif
>+#ifdef HEAD_B
>+	status = lv1_gpu_context_attribute(0x0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET, 0, 0, 1, 0);	/* head b */
>+
>+	if (status) {
>+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
>+		       __FUNCTION__, status);
>+		goto err;
>+	}
>+#endif
>+
>+	ps3fb_mode = ps3av_get_mode();
>+	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
>+#ifndef MODULE
>+	mode = ps3fb_setup(option);	/* check boot option */
>+	if (mode)
>+		ps3fb_mode = mode;
>+#endif
>+	if (ps3fb_mode > 0) {
>+		u32 xres, yres;
>+		ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
>+		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
>+		DPRINTK("res_index:%d\n", ps3fb.res_index);
>+	} else
>+		ps3fb.res_index = GPU_RES_INDEX;
>+	ps3fb.videomemorysize = ps3fb_videomemory.size;
>+
>+	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
>+	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
>+	init_MUTEX(&ps3fb.sem);
>+	init_waitqueue_head(&ps3fb.wait_vsync);
>+	ps3fb.num_frames = 1;
>+	ret = platform_driver_register(&ps3fb_driver);
>+
>+	if (!ret) {
>+		ret = platform_device_register(&ps3fb_device);
>+		if (ret)
>+			platform_driver_unregister(&ps3fb_driver);
>+	}
>+
>+	register_reboot_notifier(&ps3fb_reboot_nb);
>+	ps3fb_set_sync();
>+
>+	return ret;
>+
>+err:
>+	return -ENXIO;
>+}
>+

cheers,

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 7/9] ps3: disable display flipping during mode changes
  2007-01-25 17:51   ` Geert Uytterhoeven
  (?)
@ 2007-01-26  2:13   ` Arnd Bergmann
  -1 siblings, 0 replies; 64+ messages in thread
From: Arnd Bergmann @ 2007-01-26  2:13 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Geert Uytterhoeven, Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development

On Thursday 25 January 2007 18:51, Geert Uytterhoeven wrote:
> @@ -33,6 +33,12 @@
>  #define DPRINTK(fmt, args...) do { } while (0)
>  #endif
>  
> +#ifdef CONFIG_FB_PS3
> +extern int ps3fb_flip_ctl(int);
> +#else
> +#define ps3fb_flip_ctl(x)
> +#endif

The empty function should by convention be defined as
'do { } while (0)', like the DPRINTK above.
Even better might be an empty inline function

static inline int ps3fb_flip_ctl(int arg)
{
	return 0;
}

that enables type checking in gcc.

	Arnd <><

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-25 17:48   ` Geert Uytterhoeven
  (?)
@ 2007-01-26  3:12   ` Christoph Hellwig
  2007-01-29 14:10       ` Geert Uytterhoeven
  -1 siblings, 1 reply; 64+ messages in thread
From: Christoph Hellwig @ 2007-01-26  3:12 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development

On Thu, Jan 25, 2007 at 06:48:04PM +0100, Geert Uytterhoeven wrote:
> +EXPORT_SYMBOL(ps3av_set_audio_mode);

not _GPL?  This module seems like a very deeply internal helper for
other ps3 driver and not a general kernel API.

Btw, the Kconfig and/or top of file comment really needs a better
explanation what this "driver" is for.  I also wonder why it's
selectable in Kconfig at all given it has no visible user interface.
Shouldn't the users of the exported symbols simply pull it in or the
code made part of the unconditional build bits in the ps3 platform
directory?

> +static int ps3av_at_exit(struct notifier_block *self,
> +			 unsigned long state, void *data)
> +{
> +	/* fin avsetting modules */
> +	ps3av_cmd_fin();
> +
> +	if (!ps3av.available)
> +		return NOTIFY_OK;
> +
> +	ps3av.available = 0;
> +
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block ps3av_reboot_nb = {
> +	.notifier_call = ps3av_at_exit
> +};

Please implement this as ->shutdown method of the driver instead.
In case ps3_vuart_port_driver doesn't have that method yet please
add it as a forwarder for the generic driver model ->shutdown method.

> +#ifdef __KERNEL__

Why would you want to export the rest of this header to userspace?
(And in case you really want that you also have to add it to the Kbuild
file to actually be exported..)



and btw, please beat up the folks who designed this awfully stupid API..

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
  2007-01-25 17:51   ` Geert Uytterhoeven
  (?)
@ 2007-01-26  3:14   ` Christoph Hellwig
  2007-01-30  2:23       ` Michael Ellerman
  2007-03-24 23:46     ` Geoff Levand
  -1 siblings, 2 replies; 64+ messages in thread
From: Christoph Hellwig @ 2007-01-26  3:14 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development

On Thu, Jan 25, 2007 at 06:51:50PM +0100, Geert Uytterhoeven wrote:
> PS3: Cleanup the frame buffer device before clearing the HPTE mapping
> 
> Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> ---
>  arch/powerpc/platforms/ps3/htab.c |    5 +++++
>  1 files changed, 5 insertions(+)
> 
> --- ps3-linux.orig/arch/powerpc/platforms/ps3/htab.c
> +++ ps3-linux/arch/powerpc/platforms/ps3/htab.c
> @@ -234,6 +234,11 @@ static void ps3_hpte_invalidate(unsigned
>  
>  static void ps3_hpte_clear(void)
>  {
> +	extern void ps3fb_cleanup(void);

Externs belong into headers.

> +
> +#ifdef CONFIG_FB_PS3
> +	ps3fb_cleanup();
> +#endif

And well, adding framebuffer calls into the mmu code is rather fucked.
This at least needs a big comment explaning the hypervisor braindamage
that is responsible for this in colourfull language.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-25 17:48   ` Geert Uytterhoeven
  (?)
  (?)
@ 2007-01-26  4:13   ` Arnd Bergmann
  2007-01-26 14:56       ` Geert Uytterhoeven
  2007-01-29 15:14       ` Geert Uytterhoeven
  -1 siblings, 2 replies; 64+ messages in thread
From: Arnd Bergmann @ 2007-01-26  4:13 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Geert Uytterhoeven, Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development

On Thursday 25 January 2007 18:48, Geert Uytterhoeven wrote:
> +
> +#ifdef PS3AV_DEBUG
> +#define DPRINTK(fmt, args...) \
> +	do { printk("ps3av " fmt, ## args); } while (0)
> +#else
> +#define DPRINTK(fmt, args...) do { } while (0)
> +#endif

You should probably use the provided pr_debug or (better) dev_dbg
macros to do that now.

> +} video_mode_table[] = {
> +	{     0, }, /* auto */
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I,       A_N,  720,  480, 1, 60},
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P,       A_N,  720,  480, 0, 60},
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ,  A_N, 1280,  720, 0, 60},
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60},
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60},
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I,       A_N,  720,  576, 1, 50},
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P,       A_N,  720,  576, 0, 50},
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ,  A_N, 1280,  720, 0, 50},
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50},
> +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50},
> +	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA,       A_W, 1280,  768, 0, 60},
> +	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA,       A_N, 1280, 1024, 0, 60},
> +	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA,      A_W, 1920, 1200, 0, 60},
> +};

Is there a fundamental reason why 1280x768 is not supported as YUV? That is
the resolution that my TV set at home has natively, and I'd like to use it.

> +	if (down_interruptible(&ps3av.sem)) {
> +		printk(KERN_ERR "%s:sem failed cid:%x \n", __FUNCTION__, cid);
> +		return -ERESTARTSYS;
> +	}

This should not normally be considered an error, since a user can
trigger it easily.

> +
> +	table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
> +	if (table == NULL) {
> +		printk(KERN_ERR "%s: invalid_cid:%x\n", __FUNCTION__, cid);
> +		res = -EINVAL;
> +		goto err;
> +	}
> +
> +	if (send_len < PS3AV_HDR_SIZE) {
> +		printk(KERN_ERR "%s: invalid send_len:%d\n", __FUNCTION__,
> +		       send_len);
> +		goto err;
> +	}
> +

What's the point in these checks? All callers of your function seem to be
from kernel space, so it can't really trigger here unless there is a bug
in the model.
I guess it could either be a BUG_ON() if you want to verify the validity
of your code, or you should leave out ps3av_search_cmd_table() entirely.

> +	msleep(100);
> +
> +	/* video mute on */
> +	for (i = 0; i < num_of_av_port; i++) {
> +		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
> +		if (res < 0)
> +			return -1;
> +		if (i < num_of_hdmi_port) {
> +			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
> +						   PS3AV_CMD_MUTE_OFF);
> +			if (res < 0)
> +				return -1;
> +		}
> +	}
> +	msleep(300);

400 ms total wait time is very noticeable to the user. Is it possible to
reduce that time?

> +
> +	msleep(1500);
> +	/* av video mute */
> +	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);

This is an even longer time to wait for. What about this one?

> +#ifdef PS3AV_DEBUG
> +	ps3av_cmd_av_hw_conf_dump(&ps3av->av_hw_conf);
> +#endif

It would be better to avoid this ifdef by defining an empty function
in the header file if PS3AV_DEBUG is not set.

> +	/* set videomode */
> +	old_id = atomic_read(&ps3av.ps3av_mode);
> +	atomic_set(&ps3av.ps3av_mode, id);
> +	if (ps3av_set_videomode(id))
> +		atomic_set(&ps3av.ps3av_mode, old_id);

This is not really atomic at all. If you want the update to be
atomic here, you should probably try to use atomic_cmpxchg().
Otherwise a regular int inside of a mutex might be more appropriate.

> +EXPORT_SYMBOL(ps3av_set_video_mode);

Is it intentionally EXPORT_SYMBOL instead of EXPORT_SYMBOL_GPL?
Normally, we try to make all new symbols _GPL, though it is obviously
without your own judgment to decide on which you use.

> +
> +int ps3av_set_mode(u32 id, int boot)
> +{
> +	int res;
> +
> +	res = ps3av_set_video_mode(id, boot);
> +	if (res)
> +		return -1;
> +
> +	res = ps3av_set_audio_mode(PS3AV_CMD_AUDIO_NUM_OF_CH_2,
> +				   PS3AV_CMD_AUDIO_FS_48K,
> +				   PS3AV_CMD_AUDIO_WORD_BITS_16,
> +				   PS3AV_CMD_AUDIO_FORMAT_PCM,
> +				   PS3AV_CMD_AUDIO_SOURCE_SERIAL);
> +	if (res)
> +		return -1;
> +
> +	return 0;
> +}

Common convention would be to use -ESOMETHING instead of -1 as the return
code.

> +static u32 ps3av_cs_video2av_bitlen(int cs)
> +{
> +	u32 res = 0;
> +
> +	switch (cs) {
> +	case PS3AV_CMD_VIDEO_CS_RGB_8:
> +	case PS3AV_CMD_VIDEO_CS_YUV444_8:
> +	case PS3AV_CMD_VIDEO_CS_YUV422_8:
> +	case PS3AV_CMD_VIDEO_CS_XVYCC_8:
> +		res = PS3AV_CMD_AV_CS_8;
> +		break;
> +	case PS3AV_CMD_VIDEO_CS_RGB_10:
> +	case PS3AV_CMD_VIDEO_CS_YUV444_10:
> +	case PS3AV_CMD_VIDEO_CS_YUV422_10:
> +	case PS3AV_CMD_VIDEO_CS_XVYCC_10:
> +		res = PS3AV_CMD_AV_CS_10;
> +		break;
> +	case PS3AV_CMD_VIDEO_CS_RGB_12:
> +	case PS3AV_CMD_VIDEO_CS_YUV444_12:
> +	case PS3AV_CMD_VIDEO_CS_YUV422_12:
> +	case PS3AV_CMD_VIDEO_CS_XVYCC_12:
> +		res = PS3AV_CMD_AV_CS_12;
> +		break;
> +	default:
> +		res = PS3AV_CMD_AV_CS_8;
> +		break;
> +	}
> +	return res;
> +}
> +
> +static u32 ps3av_vid_video2av(int vid)
> +{
> +	u32 res = 0;
> +
> +	switch (vid) {
> +	case PS3AV_CMD_VIDEO_VID_480I:
> +		res = PS3AV_CMD_AV_VID_480I;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_480P:
> +		res = PS3AV_CMD_AV_VID_480P;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_576I:
> +		res = PS3AV_CMD_AV_VID_576I;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_576P:
> +		res = PS3AV_CMD_AV_VID_576P;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_1080I_60HZ:
> +		res = PS3AV_CMD_AV_VID_1080I_60HZ;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_720P_60HZ:
> +		res = PS3AV_CMD_AV_VID_720P_60HZ;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_1080P_60HZ:
> +		res = PS3AV_CMD_AV_VID_1080P_60HZ;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_1080I_50HZ:
> +		res = PS3AV_CMD_AV_VID_1080I_50HZ;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_720P_50HZ:
> +		res = PS3AV_CMD_AV_VID_720P_50HZ;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_1080P_50HZ:
> +		res = PS3AV_CMD_AV_VID_1080P_50HZ;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_WXGA:
> +		res = PS3AV_CMD_AV_VID_WXGA;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_SXGA:
> +		res = PS3AV_CMD_AV_VID_SXGA;
> +		break;
> +	case PS3AV_CMD_VIDEO_VID_WUXGA:
> +		res = PS3AV_CMD_AV_VID_WUXGA;
> +		break;
> +	default:
> +		res = PS3AV_CMD_AV_VID_480P;
> +		break;
> +	}
> +	return res;
> +}

Maybe replace these with lookup tables for smaller code size?

> +static u8 ps3av_cnv_mclk(u32 fs)
> +{
> +	u8 mclk;
> +
> +	switch (fs) {
> +	case PS3AV_CMD_AUDIO_FS_44K:
> +		mclk = PS3AV_CMD_AV_MCLK_512;
> +		break;
> +	case PS3AV_CMD_AUDIO_FS_48K:
> +		mclk = PS3AV_CMD_AV_MCLK_512;
> +		break;
> +	case PS3AV_CMD_AUDIO_FS_88K:
> +		mclk = PS3AV_CMD_AV_MCLK_256;
> +		break;
> +	case PS3AV_CMD_AUDIO_FS_96K:
> +		mclk = PS3AV_CMD_AV_MCLK_256;
> +		break;
> +	case PS3AV_CMD_AUDIO_FS_176K:
> +		mclk = PS3AV_CMD_AV_MCLK_128;
> +		break;
> +	case PS3AV_CMD_AUDIO_FS_192K:
> +		mclk = PS3AV_CMD_AV_MCLK_128;
> +		break;
> +	default:
> +		printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
> +		mclk = 0;
> +		break;
> +	}
> +	return mclk;
> +}

Same here.

> +
> +static const u32 ps3av_ns_table[][5] = {
> +	/*   D1,    D2,    D3,    D4,    D5 */
> +	{  6272,  6272, 17836, 17836,  8918 },	/*  44K */
> +	{  6144,  6144, 11648, 11648,  5824 },	/*  48K */
> +	{ 12544, 12544, 35672, 35672, 17836 },	/*  88K */
> +	{ 12288, 12288, 23296, 23296, 11648 },	/*  96K */
> +	{ 25088, 25088, 71344, 71344, 35672 },	/* 176K */
> +	{ 24576, 24576, 46592, 46592, 23296 },	/* 192K */
> +};

When writing such a table, it's often clearer to use named indexes
instead of the comments, like

static const u32 ps3av_ns_table[][5] = {
				 /*   D1,    D2,    D3,    D4,    D5 */
	[PS3AV_CMD_AUDIO_FS_44K]  {  6272,  6272, 17836, 17836,  8918 },
	[PS3AV_CMD_AUDIO_FS_48K]  {  6144,  6144, 11648, 11648,  5824 },
	[PS3AV_CMD_AUDIO_FS_88K]  { 12544, 12544, 35672, 35672, 17836 },
	[PS3AV_CMD_AUDIO_FS_96K]  { 12288, 12288, 23296, 23296, 11648 },
	[PS3AV_CMD_AUDIO_FS_176K] { 25088, 25088, 71344, 71344, 35672 },
	[PS3AV_CMD_AUDIO_FS_192K] { 24576, 24576, 46592, 46592, 23296 },
};

> +/* event_bit */
> +#define PS3AV_CMD_EVENT_BIT_UNPLUGGED			(1 << 0)
> +#define PS3AV_CMD_EVENT_BIT_PLUGGED			(1 << 1)
> +#define PS3AV_CMD_EVENT_BIT_HDCP_DONE			(1 << 2)
> +#define PS3AV_CMD_EVENT_BIT_HDCP_FAIL			(1 << 3)
> +#define PS3AV_CMD_EVENT_BIT_HDCP_REAUTH			(1 << 4)
> +#define PS3AV_CMD_EVENT_BIT_HDCP_TOPOLOGY		(1 << 5)

My personal taste is to write these as 

#define PS3AV_CMD_EVENT_BIT_UNPLUGGED			0x0001
#define PS3AV_CMD_EVENT_BIT_PLUGGED			0x0002
#define PS3AV_CMD_EVENT_BIT_HDCP_DONE			0x0004
#define PS3AV_CMD_EVENT_BIT_HDCP_FAIL			0x0008
#define PS3AV_CMD_EVENT_BIT_HDCP_REAUTH			0x0010
#define PS3AV_CMD_EVENT_BIT_HDCP_TOPOLOGY		0x0020

but just do whichever you prefer here.

> +/* for video module */
> +/* video_head */
> +#define PS3AV_CMD_VIDEO_HEAD_A				0x0000
> +#define PS3AV_CMD_VIDEO_HEAD_B				0x0001
> +/* video_cs_out video_cs_in */
> +#define PS3AV_CMD_VIDEO_CS_NONE				0x0000
> +#define PS3AV_CMD_VIDEO_CS_RGB_8			0x0001
> +#define PS3AV_CMD_VIDEO_CS_YUV444_8			0x0002
> +#define PS3AV_CMD_VIDEO_CS_YUV422_8			0x0003
> +#define PS3AV_CMD_VIDEO_CS_XVYCC_8			0x0004
> +#define PS3AV_CMD_VIDEO_CS_RGB_10			0x0005
> +#define PS3AV_CMD_VIDEO_CS_YUV444_10			0x0006
> +#define PS3AV_CMD_VIDEO_CS_YUV422_10			0x0007
> +#define PS3AV_CMD_VIDEO_CS_XVYCC_10			0x0008
> +#define PS3AV_CMD_VIDEO_CS_RGB_12			0x0009
> +#define PS3AV_CMD_VIDEO_CS_YUV444_12			0x000a
> +#define PS3AV_CMD_VIDEO_CS_YUV422_12			0x000b
> +#define PS3AV_CMD_VIDEO_CS_XVYCC_12			0x000c
> +/* video_vid */
> +#define PS3AV_CMD_VIDEO_VID_NONE			0x0000
> +#define PS3AV_CMD_VIDEO_VID_480I			0x0001
> +#define PS3AV_CMD_VIDEO_VID_576I			0x0003
> +#define PS3AV_CMD_VIDEO_VID_480P			0x0005
> +#define PS3AV_CMD_VIDEO_VID_576P			0x0006
> +#define PS3AV_CMD_VIDEO_VID_1080I_60HZ			0x0007
> +#define PS3AV_CMD_VIDEO_VID_1080I_50HZ			0x0008
> +#define PS3AV_CMD_VIDEO_VID_720P_60HZ			0x0009
> +#define PS3AV_CMD_VIDEO_VID_720P_50HZ			0x000a
> +#define PS3AV_CMD_VIDEO_VID_1080P_60HZ			0x000b
> +#define PS3AV_CMD_VIDEO_VID_1080P_50HZ			0x000c
> +#define PS3AV_CMD_VIDEO_VID_WXGA			0x000d
> +#define PS3AV_CMD_VIDEO_VID_SXGA			0x000e
> +#define PS3AV_CMD_VIDEO_VID_WUXGA			0x000f
> +#define PS3AV_CMD_VIDEO_VID_480I_A			0x0010
> +/* video_format */
> +#define PS3AV_CMD_VIDEO_FORMAT_BLACK			0x0000
> +#define PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT		0x0007
> +/* video_order */
> +#define PS3AV_CMD_VIDEO_ORDER_RGB			0x0000
> +#define PS3AV_CMD_VIDEO_ORDER_BGR			0x0001
> +/* video_fmt */
> +#define PS3AV_CMD_VIDEO_FMT_X8R8G8B8			0x0000
> +/* video_out_format */
> +#define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT		0x0000
> +/* video_sync */
> +#define PS3AV_CMD_VIDEO_SYNC_VSYNC			0x0001
> +#define PS3AV_CMD_VIDEO_SYNC_CSYNC			0x0004
> +#define PS3AV_CMD_VIDEO_SYNC_HSYNC			0x0010
> +
> +/* for audio module */
> +/* num_of_ch */
> +#define PS3AV_CMD_AUDIO_NUM_OF_CH_2			0x0000
> +#define PS3AV_CMD_AUDIO_NUM_OF_CH_3			0x0001
> +#define PS3AV_CMD_AUDIO_NUM_OF_CH_4			0x0002
> +#define PS3AV_CMD_AUDIO_NUM_OF_CH_5			0x0003
> +#define PS3AV_CMD_AUDIO_NUM_OF_CH_6			0x0004
> +#define PS3AV_CMD_AUDIO_NUM_OF_CH_7			0x0005
> +#define PS3AV_CMD_AUDIO_NUM_OF_CH_8			0x0006
> +/* audio_fs */
> +#define PS3AV_CMD_AUDIO_FS_32K				0x0001
> +#define PS3AV_CMD_AUDIO_FS_44K				0x0002
> +#define PS3AV_CMD_AUDIO_FS_48K				0x0003
> +#define PS3AV_CMD_AUDIO_FS_88K				0x0004
> +#define PS3AV_CMD_AUDIO_FS_96K				0x0005
> +#define PS3AV_CMD_AUDIO_FS_176K				0x0006
> +#define PS3AV_CMD_AUDIO_FS_192K				0x0007
> +/* audio_word_bits */
> +#define PS3AV_CMD_AUDIO_WORD_BITS_16			0x0001
> +#define PS3AV_CMD_AUDIO_WORD_BITS_20			0x0002
> +#define PS3AV_CMD_AUDIO_WORD_BITS_24			0x0003
> +/* audio_format */
> +#define PS3AV_CMD_AUDIO_FORMAT_PCM			0x0001
> +#define PS3AV_CMD_AUDIO_FORMAT_BITSTREAM		0x00ff
> +/* audio_source */
> +#define PS3AV_CMD_AUDIO_SOURCE_SERIAL			0x0000
> +#define PS3AV_CMD_AUDIO_SOURCE_SPDIF			0x0001
> +/* audio_swap */
> +#define PS3AV_CMD_AUDIO_SWAP_0				0x0000
> +#define PS3AV_CMD_AUDIO_SWAP_1				0x0000
> +/* audio_map */
> +#define PS3AV_CMD_AUDIO_MAP_OUTPUT_0			0x0000
> +#define PS3AV_CMD_AUDIO_MAP_OUTPUT_1			0x0001
> +#define PS3AV_CMD_AUDIO_MAP_OUTPUT_2			0x0002
> +#define PS3AV_CMD_AUDIO_MAP_OUTPUT_3			0x0003
> +/* audio_layout */
> +#define PS3AV_CMD_AUDIO_LAYOUT_2CH			0x0000
> +#define PS3AV_CMD_AUDIO_LAYOUT_6CH			0x000b	/* LREClr */
> +#define PS3AV_CMD_AUDIO_LAYOUT_8CH			0x001f	/* LREClrXY */
> +/* audio_downmix */
> +#define PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED		0x0000
> +#define PS3AV_CMD_AUDIO_DOWNMIX_PROHIBITED		0x0001
> +
> +/* audio_port */
> +#define PS3AV_CMD_AUDIO_PORT_HDMI_0			( 1 << 0 )
> +#define PS3AV_CMD_AUDIO_PORT_HDMI_1			( 1 << 1 )
> +#define PS3AV_CMD_AUDIO_PORT_AVMULTI_0			( 1 << 10 )
> +#define PS3AV_CMD_AUDIO_PORT_SPDIF_0			( 1 << 20 )
> +#define PS3AV_CMD_AUDIO_PORT_SPDIF_1			( 1 << 21 )
> +
> +/* audio_ctrl_id */
> +#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_RESET		0x0000
> +#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_DE_EMPHASIS		0x0001
> +#define PS3AV_CMD_AUDIO_CTRL_ID_AVCLK			0x0002
> +/* audio_ctrl_data[0] reset */
> +#define PS3AV_CMD_AUDIO_CTRL_RESET_NEGATE		0x0000
> +#define PS3AV_CMD_AUDIO_CTRL_RESET_ASSERT		0x0001
> +/* audio_ctrl_data[0] de-emphasis */
> +#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_OFF		0x0000
> +#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_ON		0x0001
> +/* audio_ctrl_data[0] avclk */
> +#define PS3AV_CMD_AUDIO_CTRL_AVCLK_22			0x0000
> +#define PS3AV_CMD_AUDIO_CTRL_AVCLK_18			0x0001
> +
> +/* av_vid */
> +/* do not use these params directly, use vid_video2av */
> +#define PS3AV_CMD_AV_VID_480I				0x0000
> +#define PS3AV_CMD_AV_VID_480P				0x0001
> +#define PS3AV_CMD_AV_VID_720P_60HZ			0x0002
> +#define PS3AV_CMD_AV_VID_1080I_60HZ			0x0003
> +#define PS3AV_CMD_AV_VID_1080P_60HZ			0x0004
> +#define PS3AV_CMD_AV_VID_576I				0x0005
> +#define PS3AV_CMD_AV_VID_576P				0x0006
> +#define PS3AV_CMD_AV_VID_720P_50HZ			0x0007
> +#define PS3AV_CMD_AV_VID_1080I_50HZ			0x0008
> +#define PS3AV_CMD_AV_VID_1080P_50HZ			0x0009
> +#define PS3AV_CMD_AV_VID_WXGA				0x000a
> +#define PS3AV_CMD_AV_VID_SXGA				0x000b
> +#define PS3AV_CMD_AV_VID_WUXGA				0x000c
> +/* av_cs_out av_cs_in */
> +/* use cs_video2av() */
> +#define PS3AV_CMD_AV_CS_RGB_8				0x0000
> +#define PS3AV_CMD_AV_CS_YUV444_8			0x0001
> +#define PS3AV_CMD_AV_CS_YUV422_8			0x0002
> +#define PS3AV_CMD_AV_CS_XVYCC_8				0x0003
> +#define PS3AV_CMD_AV_CS_RGB_10				0x0004
> +#define PS3AV_CMD_AV_CS_YUV444_10			0x0005
> +#define PS3AV_CMD_AV_CS_YUV422_10			0x0006
> +#define PS3AV_CMD_AV_CS_XVYCC_10			0x0007
> +#define PS3AV_CMD_AV_CS_RGB_12				0x0008
> +#define PS3AV_CMD_AV_CS_YUV444_12			0x0009
> +#define PS3AV_CMD_AV_CS_YUV422_12			0x000a
> +#define PS3AV_CMD_AV_CS_XVYCC_12			0x000b
> +#define PS3AV_CMD_AV_CS_8				0x0000
> +#define PS3AV_CMD_AV_CS_10				0x0001
> +#define PS3AV_CMD_AV_CS_12				0x0002
> +/* dither */
> +#define PS3AV_CMD_AV_DITHER_OFF				0x0000
> +#define PS3AV_CMD_AV_DITHER_ON				0x0001
> +#define PS3AV_CMD_AV_DITHER_8BIT			0x0000
> +#define PS3AV_CMD_AV_DITHER_10BIT			0x0002
> +#define PS3AV_CMD_AV_DITHER_12BIT			0x0004
> +/* super_white */
> +#define PS3AV_CMD_AV_SUPER_WHITE_OFF			0x0000
> +#define PS3AV_CMD_AV_SUPER_WHITE_ON			0x0001
> +/* aspect */
> +#define PS3AV_CMD_AV_ASPECT_16_9			0x0000
> +#define PS3AV_CMD_AV_ASPECT_4_3				0x0001
> +/* video_cs_cnv() */
> +#define PS3AV_CMD_VIDEO_CS_RGB				0x0001
> +#define PS3AV_CMD_VIDEO_CS_YUV422			0x0002
> +#define PS3AV_CMD_VIDEO_CS_YUV444			0x0003
> +
> +/* for automode */
> +#define PS3AV_RESBIT_720x480P			0x0003	/* 0x0001 | 0x0002 */
> +#define PS3AV_RESBIT_720x576P			0x0003	/* 0x0001 | 0x0002 */
> +#define PS3AV_RESBIT_1280x720P			0x0004
> +#define PS3AV_RESBIT_1920x1080I			0x0008
> +#define PS3AV_RESBIT_1920x1080P			0x4000
> +#define PS3AV_RES_MASK_60			(PS3AV_RESBIT_720x480P \
> +						| PS3AV_RESBIT_1280x720P \
> +						| PS3AV_RESBIT_1920x1080I \
> +						| PS3AV_RESBIT_1920x1080P)
> +#define PS3AV_RES_MASK_50			(PS3AV_RESBIT_720x576P \
> +						| PS3AV_RESBIT_1280x720P \
> +						| PS3AV_RESBIT_1920x1080I \
> +						| PS3AV_RESBIT_1920x1080P)
> +
> +#define PS3AV_MONITOR_TYPE_HDMI			1	/* HDMI */
> +#define PS3AV_MONITOR_TYPE_DVI			2	/* DVI */
> +#define PS3AV_DEFAULT_HDMI_VID_REG_60		PS3AV_CMD_VIDEO_VID_480P
> +#define PS3AV_DEFAULT_AVMULTI_VID_REG_60	PS3AV_CMD_VIDEO_VID_480I
> +#define PS3AV_DEFAULT_HDMI_VID_REG_50		PS3AV_CMD_VIDEO_VID_576P
> +#define PS3AV_DEFAULT_AVMULTI_VID_REG_50	PS3AV_CMD_VIDEO_VID_576I
> +#define PS3AV_DEFAULT_DVI_VID			PS3AV_CMD_VIDEO_VID_480P
> +
> +#define PS3AV_REGION_60				0x01
> +#define PS3AV_REGION_50				0x02
> +#define PS3AV_REGION_RGB			0x10
> +
> +#define get_status(buf)				(((__u32 *)buf)[2])
> +#define PS3AV_HDR_SIZE				4	/* version + size */
> +
> +/* for video mode */
> +#define PS3AV_MODE_MASK				0x000F
> +#define PS3AV_MODE_HDCP_OFF			0x1000	/* Retail PS3 product doesn't support this */
> +#define PS3AV_MODE_DITHER			0x0800
> +#define PS3AV_MODE_FULL				0x0080
> +#define PS3AV_MODE_DVI				0x0040
> +#define PS3AV_MODE_RGB				0x0020
> +
> +#ifdef __KERNEL__

If the definitions below are kernel-only, does that mean you want everything above
to be exported to user space? Is that necessary?

> +struct ps3av {
> +	int available;
> +	struct semaphore sem;

The semaphore should most likely be a 'struct mutex' instead.

	Arnd <><

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-26  4:13   ` Arnd Bergmann
@ 2007-01-26 14:56       ` Geert Uytterhoeven
  2007-01-29 15:14       ` Geert Uytterhoeven
  1 sibling, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-26 14:56 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linuxppc-dev, James Simmons,
	Linux Frame Buffer Device Development, Paul Mackerras

On Fri, 26 Jan 2007, Arnd Bergmann wrote:
> > +} video_mode_table[] = {
> > +	{     0, }, /* auto */
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I,       A_N,  720,  480, 1, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P,       A_N,  720,  480, 0, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ,  A_N, 1280,  720, 0, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I,       A_N,  720,  576, 1, 50},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P,       A_N,  720,  576, 0, 50},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ,  A_N, 1280,  720, 0, 50},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50},
> > +	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA,       A_W, 1280,  768, 0, 60},
> > +	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA,       A_N, 1280, 1024, 0, 60},
> > +	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA,      A_W, 1920, 1200, 0, 60},
> > +};
> 
> Is there a fundamental reason why 1280x768 is not supported as YUV? That is
> the resolution that my TV set at home has natively, and I'd like to use it.

Analog YUV (Component and composite/S-video) video timings are dictated by
broadcast standards.

The last 3 resolutions are supported through the HDMI output only. Hence if
your TV has HDMI or DVI-D (_with_ HDCP, else you get a black screen) inputs,
you can use 1280x768.

If your TV doesn't have HDMI or DVI-D with HDCP, but it has component inputs,
you can use analog 720p.

> > +	msleep(100);
> > +
> > +	/* video mute on */
> > +	for (i = 0; i < num_of_av_port; i++) {
> > +		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
> > +		if (res < 0)
> > +			return -1;
> > +		if (i < num_of_hdmi_port) {
> > +			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
> > +						   PS3AV_CMD_MUTE_OFF);
> > +			if (res < 0)
> > +				return -1;
> > +		}
> > +	}
> > +	msleep(300);
> 
> 400 ms total wait time is very noticeable to the user. Is it possible to
> reduce that time?
> 
> > +
> > +	msleep(1500);
> > +	/* av video mute */
> > +	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);
> 
> This is an even longer time to wait for. What about this one?

Reducing these values may cause video noise to be seen when changing video
modes.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
@ 2007-01-26 14:56       ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-26 14:56 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linuxppc-dev, James Simmons,
	Linux Frame Buffer Device Development, Paul Mackerras

On Fri, 26 Jan 2007, Arnd Bergmann wrote:
> > +} video_mode_table[] = {
> > +	{     0, }, /* auto */
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I,       A_N,  720,  480, 1, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P,       A_N,  720,  480, 0, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ,  A_N, 1280,  720, 0, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I,       A_N,  720,  576, 1, 50},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P,       A_N,  720,  576, 0, 50},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ,  A_N, 1280,  720, 0, 50},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50},
> > +	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50},
> > +	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA,       A_W, 1280,  768, 0, 60},
> > +	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA,       A_N, 1280, 1024, 0, 60},
> > +	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA,      A_W, 1920, 1200, 0, 60},
> > +};
> 
> Is there a fundamental reason why 1280x768 is not supported as YUV? That is
> the resolution that my TV set at home has natively, and I'd like to use it.

Analog YUV (Component and composite/S-video) video timings are dictated by
broadcast standards.

The last 3 resolutions are supported through the HDMI output only. Hence if
your TV has HDMI or DVI-D (_with_ HDCP, else you get a black screen) inputs,
you can use 1280x768.

If your TV doesn't have HDMI or DVI-D with HDCP, but it has component inputs,
you can use analog 720p.

> > +	msleep(100);
> > +
> > +	/* video mute on */
> > +	for (i = 0; i < num_of_av_port; i++) {
> > +		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
> > +		if (res < 0)
> > +			return -1;
> > +		if (i < num_of_hdmi_port) {
> > +			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
> > +						   PS3AV_CMD_MUTE_OFF);
> > +			if (res < 0)
> > +				return -1;
> > +		}
> > +	}
> > +	msleep(300);
> 
> 400 ms total wait time is very noticeable to the user. Is it possible to
> reduce that time?
> 
> > +
> > +	msleep(1500);
> > +	/* av video mute */
> > +	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);
> 
> This is an even longer time to wait for. What about this one?

Reducing these values may cause video noise to be seen when changing video
modes.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-26 14:56       ` Geert Uytterhoeven
@ 2007-01-28 21:37         ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 64+ messages in thread
From: Benjamin Herrenschmidt @ 2007-01-28 21:37 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: linuxppc-dev, Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Arnd Bergmann

> Analog YUV (Component and composite/S-video) video timings are dictated by
> broadcast standards.
> 
> The last 3 resolutions are supported through the HDMI output only. Hence if
> your TV has HDMI or DVI-D (_with_ HDCP, else you get a black screen) inputs,
> you can use 1280x768.
> 
> If your TV doesn't have HDMI or DVI-D with HDCP, but it has component inputs,
> you can use analog 720p.

Please, still try to get the HV folks to add more VESA modes for use by
linux :-) 1600x1200 would be nice for example, as would 1440x900 (lots
of cheap flat panels do that nowadays.... they can demote to 720p which
is good enough for games, but for linux, we want native resolution).

> Reducing these values may cause video noise to be seen when changing video
> modes.

So the whole thing should be turned into a state machine on a timer or a
kthread no ? So at least, whatever issues the mode change can start
drawing while the kernel waits to actually enable the outputs...

Ben.



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
@ 2007-01-28 21:37         ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 64+ messages in thread
From: Benjamin Herrenschmidt @ 2007-01-28 21:37 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: linuxppc-dev, Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Arnd Bergmann

> Analog YUV (Component and composite/S-video) video timings are dictated by
> broadcast standards.
> 
> The last 3 resolutions are supported through the HDMI output only. Hence if
> your TV has HDMI or DVI-D (_with_ HDCP, else you get a black screen) inputs,
> you can use 1280x768.
> 
> If your TV doesn't have HDMI or DVI-D with HDCP, but it has component inputs,
> you can use analog 720p.

Please, still try to get the HV folks to add more VESA modes for use by
linux :-) 1600x1200 would be nice for example, as would 1440x900 (lots
of cheap flat panels do that nowadays.... they can demote to 720p which
is good enough for games, but for linux, we want native resolution).

> Reducing these values may cause video noise to be seen when changing video
> modes.

So the whole thing should be turned into a state machine on a timer or a
kthread no ? So at least, whatever issues the mode change can start
drawing while the kernel waits to actually enable the outputs...

Ben.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-26  3:12   ` Christoph Hellwig
@ 2007-01-29 14:10       ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-29 14:10 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development

On Fri, 26 Jan 2007, Christoph Hellwig wrote:
> Btw, the Kconfig and/or top of file comment really needs a better
> explanation what this "driver" is for.  I also wonder why it's

What about `PS3 AV settings driver library' instead of `PS3 AV controller
support'?

> selectable in Kconfig at all given it has no visible user interface.
> Shouldn't the users of the exported symbols simply pull it in or the
> code made part of the unconditional build bits in the ps3 platform
> directory?

We can make FB_PS3 (and SND_PS3 later) select PS3_PS3AV. Is that better?
I prefer not to make it unconditional, as people who want to run their PS3s
headless don't need it.

I guess you want us to do the same for the virtual uart, i.e. let PS3_PS3AV and
PS3_SYS_MANAGER select PS3_VUART?

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
@ 2007-01-29 14:10       ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-29 14:10 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development

On Fri, 26 Jan 2007, Christoph Hellwig wrote:
> Btw, the Kconfig and/or top of file comment really needs a better
> explanation what this "driver" is for.  I also wonder why it's

What about `PS3 AV settings driver library' instead of `PS3 AV controller
support'?

> selectable in Kconfig at all given it has no visible user interface.
> Shouldn't the users of the exported symbols simply pull it in or the
> code made part of the unconditional build bits in the ps3 platform
> directory?

We can make FB_PS3 (and SND_PS3 later) select PS3_PS3AV. Is that better?
I prefer not to make it unconditional, as people who want to run their PS3s
headless don't need it.

I guess you want us to do the same for the virtual uart, i.e. let PS3_PS3AV and
PS3_SYS_MANAGER select PS3_VUART?

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-26  4:13   ` Arnd Bergmann
@ 2007-01-29 15:14       ` Geert Uytterhoeven
  2007-01-29 15:14       ` Geert Uytterhoeven
  1 sibling, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-29 15:14 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linuxppc-dev, James Simmons,
	Linux Frame Buffer Device Development, Paul Mackerras

On Fri, 26 Jan 2007, Arnd Bergmann wrote:
> On Thursday 25 January 2007 18:48, Geert Uytterhoeven wrote:
> > +#ifdef PS3AV_DEBUG
> > +#define DPRINTK(fmt, args...) \
> > +	do { printk("ps3av " fmt, ## args); } while (0)
> > +#else
> > +#define DPRINTK(fmt, args...) do { } while (0)
> > +#endif
> 
> You should probably use the provided pr_debug or (better) dev_dbg
> macros to do that now.

Except that it's difficult to get a struct device * in drivers/ps3/ps3av_cmd.c.
And I prefer not to make ps3av_dev (which is currently static) global.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
@ 2007-01-29 15:14       ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-29 15:14 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linuxppc-dev, James Simmons,
	Linux Frame Buffer Device Development, Paul Mackerras

On Fri, 26 Jan 2007, Arnd Bergmann wrote:
> On Thursday 25 January 2007 18:48, Geert Uytterhoeven wrote:
> > +#ifdef PS3AV_DEBUG
> > +#define DPRINTK(fmt, args...) \
> > +	do { printk("ps3av " fmt, ## args); } while (0)
> > +#else
> > +#define DPRINTK(fmt, args...) do { } while (0)
> > +#endif
> 
> You should probably use the provided pr_debug or (better) dev_dbg
> macros to do that now.

Except that it's difficult to get a struct device * in drivers/ps3/ps3av_cmd.c.
And I prefer not to make ps3av_dev (which is currently static) global.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-29 14:10       ` Geert Uytterhoeven
@ 2007-01-29 16:15         ` Christoph Hellwig
  -1 siblings, 0 replies; 64+ messages in thread
From: Christoph Hellwig @ 2007-01-29 16:15 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Paul Mackerras, Linux Frame Buffer Device Development,
	James Simmons, Christoph Hellwig, Linux/PPC Development

On Mon, Jan 29, 2007 at 03:10:16PM +0100, Geert Uytterhoeven wrote:
> On Fri, 26 Jan 2007, Christoph Hellwig wrote:
> > Btw, the Kconfig and/or top of file comment really needs a better
> > explanation what this "driver" is for.  I also wonder why it's
> 
> What about `PS3 AV settings driver library' instead of `PS3 AV controller
> support'?

Makes a little more sense, yes.

> We can make FB_PS3 (and SND_PS3 later) select PS3_PS3AV. Is that better?
> I prefer not to make it unconditional, as people who want to run their PS3s
> headless don't need it.

Ok.  Even better would be handling it on the makefile level, by doing

obj-$(CONFIG_FB_PS3)	+= ps3_av.o
obj-$(CONFIG_SND_PS3)	+= ps3_av.o

> I guess you want us to do the same for the virtual uart, i.e. let PS3_PS3AV and
> PS3_SYS_MANAGER select PS3_VUART?

Yes, that probably makes sense aswell.


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
@ 2007-01-29 16:15         ` Christoph Hellwig
  0 siblings, 0 replies; 64+ messages in thread
From: Christoph Hellwig @ 2007-01-29 16:15 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Paul Mackerras, Linux Frame Buffer Device Development,
	James Simmons, Linux/PPC Development

On Mon, Jan 29, 2007 at 03:10:16PM +0100, Geert Uytterhoeven wrote:
> On Fri, 26 Jan 2007, Christoph Hellwig wrote:
> > Btw, the Kconfig and/or top of file comment really needs a better
> > explanation what this "driver" is for.  I also wonder why it's
> 
> What about `PS3 AV settings driver library' instead of `PS3 AV controller
> support'?

Makes a little more sense, yes.

> We can make FB_PS3 (and SND_PS3 later) select PS3_PS3AV. Is that better?
> I prefer not to make it unconditional, as people who want to run their PS3s
> headless don't need it.

Ok.  Even better would be handling it on the makefile level, by doing

obj-$(CONFIG_FB_PS3)	+= ps3_av.o
obj-$(CONFIG_SND_PS3)	+= ps3_av.o

> I guess you want us to do the same for the virtual uart, i.e. let PS3_PS3AV and
> PS3_SYS_MANAGER select PS3_VUART?

Yes, that probably makes sense aswell.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-29 16:15         ` Christoph Hellwig
  (?)
@ 2007-01-29 19:24         ` Geoff Levand
  -1 siblings, 0 replies; 64+ messages in thread
From: Geoff Levand @ 2007-01-29 19:24 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Geert Uytterhoeven, Linux Frame Buffer Device Development,
	Paul Mackerras, James Simmons, Linux/PPC Development

Christoph Hellwig wrote:
>> I guess you want us to do the same for the virtual uart, i.e. let PS3_PS3AV and
>> PS3_SYS_MANAGER select PS3_VUART?
> 
> Yes, that probably makes sense aswell.

I'll start work on sys-manager soon, so I'll set this up.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-29 15:14       ` Geert Uytterhoeven
@ 2007-01-30  0:16         ` Arnd Bergmann
  -1 siblings, 0 replies; 64+ messages in thread
From: Arnd Bergmann @ 2007-01-30  0:16 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: linuxppc-dev, James Simmons,
	Linux Frame Buffer Device Development, Paul Mackerras

On Monday 29 January 2007 16:14, Geert Uytterhoeven wrote:
> 
> > You should probably use the provided pr_debug or (better) dev_dbg
> > macros to do that now.
> 
> Except that it's difficult to get a struct device * in drivers/ps3/ps3av_cmd.c.
> And I prefer not to make ps3av_dev (which is currently static) global.

Ok, as I said, dev_dbg is the preferred way, but of course it only
works when you carry a device along. If you don't have one, use
pr_debug().

	Arnd <><

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
@ 2007-01-30  0:16         ` Arnd Bergmann
  0 siblings, 0 replies; 64+ messages in thread
From: Arnd Bergmann @ 2007-01-30  0:16 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: linuxppc-dev, James Simmons,
	Linux Frame Buffer Device Development, Paul Mackerras

On Monday 29 January 2007 16:14, Geert Uytterhoeven wrote:
> 
> > You should probably use the provided pr_debug or (better) dev_dbg
> > macros to do that now.
> 
> Except that it's difficult to get a struct device * in drivers/ps3/ps3av_cmd.c.
> And I prefer not to make ps3av_dev (which is currently static) global.

Ok, as I said, dev_dbg is the preferred way, but of course it only
works when you carry a device along. If you don't have one, use
pr_debug().

	Arnd <><

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
  2007-01-26  3:14   ` Christoph Hellwig
@ 2007-01-30  2:23       ` Michael Ellerman
  2007-03-24 23:46     ` Geoff Levand
  1 sibling, 0 replies; 64+ messages in thread
From: Michael Ellerman @ 2007-01-30  2:23 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: James Simmons, Linux Frame Buffer Device Development,
	Paul Mackerras, Linux/PPC Development


[-- Attachment #1.1: Type: text/plain, Size: 1265 bytes --]

On Fri, 2007-01-26 at 04:14 +0100, Christoph Hellwig wrote:
> On Thu, Jan 25, 2007 at 06:51:50PM +0100, Geert Uytterhoeven wrote:
> > PS3: Cleanup the frame buffer device before clearing the HPTE mapping
> > 
> > Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> > ---
> >  arch/powerpc/platforms/ps3/htab.c |    5 +++++
> >  1 files changed, 5 insertions(+)
> > 
> > --- ps3-linux.orig/arch/powerpc/platforms/ps3/htab.c
> > +++ ps3-linux/arch/powerpc/platforms/ps3/htab.c
> > @@ -234,6 +234,11 @@ static void ps3_hpte_invalidate(unsigned
> >  
> >  static void ps3_hpte_clear(void)
> >  {
> > +	extern void ps3fb_cleanup(void);
> 
> Externs belong into headers.
> 
> > +
> > +#ifdef CONFIG_FB_PS3
> > +	ps3fb_cleanup();
> > +#endif

And when you move it into a header, create a dummy version so you can
remove the #ifdef in the C code. eg:

#ifdef CONFIG_FB_PS3
extern void ps3fb_cleanup(void);
#else
static inline void ps3fb_cleanup(void) { };
#endif

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

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

[-- Attachment #2: Type: text/plain, Size: 146 bytes --]

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
@ 2007-01-30  2:23       ` Michael Ellerman
  0 siblings, 0 replies; 64+ messages in thread
From: Michael Ellerman @ 2007-01-30  2:23 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: James Simmons, Linux Frame Buffer Device Development,
	Paul Mackerras, Linux/PPC Development

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

On Fri, 2007-01-26 at 04:14 +0100, Christoph Hellwig wrote:
> On Thu, Jan 25, 2007 at 06:51:50PM +0100, Geert Uytterhoeven wrote:
> > PS3: Cleanup the frame buffer device before clearing the HPTE mapping
> > 
> > Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> > ---
> >  arch/powerpc/platforms/ps3/htab.c |    5 +++++
> >  1 files changed, 5 insertions(+)
> > 
> > --- ps3-linux.orig/arch/powerpc/platforms/ps3/htab.c
> > +++ ps3-linux/arch/powerpc/platforms/ps3/htab.c
> > @@ -234,6 +234,11 @@ static void ps3_hpte_invalidate(unsigned
> >  
> >  static void ps3_hpte_clear(void)
> >  {
> > +	extern void ps3fb_cleanup(void);
> 
> Externs belong into headers.
> 
> > +
> > +#ifdef CONFIG_FB_PS3
> > +	ps3fb_cleanup();
> > +#endif

And when you move it into a header, create a dummy version so you can
remove the #ifdef in the C code. eg:

#ifdef CONFIG_FB_PS3
extern void ps3fb_cleanup(void);
#else
static inline void ps3fb_cleanup(void) { };
#endif

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
  2007-01-25 17:50   ` Geert Uytterhoeven
@ 2007-01-30  2:29     ` Michael Ellerman
  -1 siblings, 0 replies; 64+ messages in thread
From: Michael Ellerman @ 2007-01-30  2:29 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development


[-- Attachment #1.1: Type: text/plain, Size: 1153 bytes --]

On Thu, 2007-01-25 at 18:50 +0100, Geert Uytterhoeven wrote:
> Preallocate bootmem memory for the PS3 frame buffer device, which needs a
> large block of physically-contiguous memory. The size of this memory block is
> configurable:
>   - The config option CONFIG_FB_PS3_DEFAULT_SIZE_M allows to specify the
>     default amount of memory (in MiB) allocated to the virtual frame buffer.
>   - The early boot parameter `ps3fb=xxx' allows to override the default value.
>     It will be rounded up to a multiple of 1 MiB, if needed.
> 
> Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>

Rather than doing the alloc in setup.c, defining a structure to the hold
the params, and then exporting the structure - why don't you just do the
alloc in the ps3 fb driver code, and have it all private in there?

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

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

[-- Attachment #2: Type: text/plain, Size: 146 bytes --]

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
@ 2007-01-30  2:29     ` Michael Ellerman
  0 siblings, 0 replies; 64+ messages in thread
From: Michael Ellerman @ 2007-01-30  2:29 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development

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

On Thu, 2007-01-25 at 18:50 +0100, Geert Uytterhoeven wrote:
> Preallocate bootmem memory for the PS3 frame buffer device, which needs a
> large block of physically-contiguous memory. The size of this memory block is
> configurable:
>   - The config option CONFIG_FB_PS3_DEFAULT_SIZE_M allows to specify the
>     default amount of memory (in MiB) allocated to the virtual frame buffer.
>   - The early boot parameter `ps3fb=xxx' allows to override the default value.
>     It will be rounded up to a multiple of 1 MiB, if needed.
> 
> Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>

Rather than doing the alloc in setup.c, defining a structure to the hold
the params, and then exporting the structure - why don't you just do the
alloc in the ps3 fb driver code, and have it all private in there?

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
  2007-01-30  2:29     ` Michael Ellerman
@ 2007-01-30  8:16       ` Geert Uytterhoeven
  -1 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-30  8:16 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development

On Tue, 30 Jan 2007, Michael Ellerman wrote:
> On Thu, 2007-01-25 at 18:50 +0100, Geert Uytterhoeven wrote:
> > Preallocate bootmem memory for the PS3 frame buffer device, which needs a
> > large block of physically-contiguous memory. The size of this memory block is
> > configurable:
> >   - The config option CONFIG_FB_PS3_DEFAULT_SIZE_M allows to specify the
> >     default amount of memory (in MiB) allocated to the virtual frame buffer.
> >   - The early boot parameter `ps3fb=xxx' allows to override the default value.
> >     It will be rounded up to a multiple of 1 MiB, if needed.
> > 
> > Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> > Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
> 
> Rather than doing the alloc in setup.c, defining a structure to the hold
> the params, and then exporting the structure - why don't you just do the
> alloc in the ps3 fb driver code, and have it all private in there?

Because at that time it's no longer possible to allocate such a big block of
memory.

We have a similar problem with the storage driver, which needs a block of 256
KiB of contiguous memory.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
@ 2007-01-30  8:16       ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-30  8:16 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development

On Tue, 30 Jan 2007, Michael Ellerman wrote:
> On Thu, 2007-01-25 at 18:50 +0100, Geert Uytterhoeven wrote:
> > Preallocate bootmem memory for the PS3 frame buffer device, which needs a
> > large block of physically-contiguous memory. The size of this memory block is
> > configurable:
> >   - The config option CONFIG_FB_PS3_DEFAULT_SIZE_M allows to specify the
> >     default amount of memory (in MiB) allocated to the virtual frame buffer.
> >   - The early boot parameter `ps3fb=xxx' allows to override the default value.
> >     It will be rounded up to a multiple of 1 MiB, if needed.
> > 
> > Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> > Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
> 
> Rather than doing the alloc in setup.c, defining a structure to the hold
> the params, and then exporting the structure - why don't you just do the
> alloc in the ps3 fb driver code, and have it all private in there?

Because at that time it's no longer possible to allocate such a big block of
memory.

We have a similar problem with the storage driver, which needs a block of 256
KiB of contiguous memory.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
  2007-01-30  8:16       ` Geert Uytterhoeven
@ 2007-01-30  8:27         ` Arnd Bergmann
  -1 siblings, 0 replies; 64+ messages in thread
From: Arnd Bergmann @ 2007-01-30  8:27 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Geert Uytterhoeven, Michael Ellerman,
	Linux Frame Buffer Device Development, Paul Mackerras,
	James Simmons

On Tuesday 30 January 2007 09:16, Geert Uytterhoeven wrote:
> We have a similar problem with the storage driver, which needs a block of 256
> KiB of contiguous memory.

I guess at least that one should be solveable. If the 256kb is only
internal flash access, it is should not be part of the storage driver
but of whatever else is used to drive this.

Assuming the module gets loaded shortly after boot, you can still allocate
256kb practically always, using get_free_pages().

	Arnd <><

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
@ 2007-01-30  8:27         ` Arnd Bergmann
  0 siblings, 0 replies; 64+ messages in thread
From: Arnd Bergmann @ 2007-01-30  8:27 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Geert Uytterhoeven, Linux Frame Buffer Device Development,
	Paul Mackerras, James Simmons

On Tuesday 30 January 2007 09:16, Geert Uytterhoeven wrote:
> We have a similar problem with the storage driver, which needs a block of 256
> KiB of contiguous memory.

I guess at least that one should be solveable. If the 256kb is only
internal flash access, it is should not be part of the storage driver
but of whatever else is used to drive this.

Assuming the module gets loaded shortly after boot, you can still allocate
256kb practically always, using get_free_pages().

	Arnd <><

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
  2007-01-30  8:27         ` Arnd Bergmann
@ 2007-01-30  8:36           ` Geert Uytterhoeven
  -1 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-30  8:36 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Michael Ellerman, linuxppc-dev,
	Linux Frame Buffer Device Development, Paul Mackerras,
	James Simmons

On Tue, 30 Jan 2007, Arnd Bergmann wrote:
> On Tuesday 30 January 2007 09:16, Geert Uytterhoeven wrote:
> > We have a similar problem with the storage driver, which needs a block of 256
> > KiB of contiguous memory.
> 
> I guess at least that one should be solveable. If the 256kb is only
> internal flash access, it is should not be part of the storage driver
> but of whatever else is used to drive this.

If we convert the FLASH part to a character device driver, the 256 KiB will be
internal to the character device driver.

> Assuming the module gets loaded shortly after boot, you can still allocate
> 256kb practically always, using get_free_pages().

I'm afraid that assumption is usually false, as you only need to access the
FLASH when you want to change boot flags or update the boot loader.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
@ 2007-01-30  8:36           ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-30  8:36 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linuxppc-dev, Linux Frame Buffer Device Development,
	Paul Mackerras, James Simmons

On Tue, 30 Jan 2007, Arnd Bergmann wrote:
> On Tuesday 30 January 2007 09:16, Geert Uytterhoeven wrote:
> > We have a similar problem with the storage driver, which needs a block of 256
> > KiB of contiguous memory.
> 
> I guess at least that one should be solveable. If the 256kb is only
> internal flash access, it is should not be part of the storage driver
> but of whatever else is used to drive this.

If we convert the FLASH part to a character device driver, the 256 KiB will be
internal to the character device driver.

> Assuming the module gets loaded shortly after boot, you can still allocate
> 256kb practically always, using get_free_pages().

I'm afraid that assumption is usually false, as you only need to access the
FLASH when you want to change boot flags or update the boot loader.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
  2007-01-30  8:36           ` Geert Uytterhoeven
@ 2007-01-30  9:08             ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 64+ messages in thread
From: Benjamin Herrenschmidt @ 2007-01-30  9:08 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: James Simmons, linuxppc-dev, Paul Mackerras,
	Linux Frame Buffer Device Development, Arnd Bergmann

On Tue, 2007-01-30 at 09:36 +0100, Geert Uytterhoeven wrote:
> On Tue, 30 Jan 2007, Arnd Bergmann wrote:
> > On Tuesday 30 January 2007 09:16, Geert Uytterhoeven wrote:
> > > We have a similar problem with the storage driver, which needs a block of 256
> > > KiB of contiguous memory.
> > 
> > I guess at least that one should be solveable. If the 256kb is only
> > internal flash access, it is should not be part of the storage driver
> > but of whatever else is used to drive this.
> 
> If we convert the FLASH part to a character device driver, the 256 KiB will be
> internal to the character device driver.
> 
> > Assuming the module gets loaded shortly after boot, you can still allocate
> > 256kb practically always, using get_free_pages().
> 
> I'm afraid that assumption is usually false, as you only need to access the
> FLASH when you want to change boot flags or update the boot loader.

At the same time, flash doesn't have to be fast... can't we use a
smaller bounce buffer (a page) and divide the transfer ?

Ben.



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
@ 2007-01-30  9:08             ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 64+ messages in thread
From: Benjamin Herrenschmidt @ 2007-01-30  9:08 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: James Simmons, linuxppc-dev, Paul Mackerras,
	Linux Frame Buffer Device Development, Arnd Bergmann

On Tue, 2007-01-30 at 09:36 +0100, Geert Uytterhoeven wrote:
> On Tue, 30 Jan 2007, Arnd Bergmann wrote:
> > On Tuesday 30 January 2007 09:16, Geert Uytterhoeven wrote:
> > > We have a similar problem with the storage driver, which needs a block of 256
> > > KiB of contiguous memory.
> > 
> > I guess at least that one should be solveable. If the 256kb is only
> > internal flash access, it is should not be part of the storage driver
> > but of whatever else is used to drive this.
> 
> If we convert the FLASH part to a character device driver, the 256 KiB will be
> internal to the character device driver.
> 
> > Assuming the module gets loaded shortly after boot, you can still allocate
> > 256kb practically always, using get_free_pages().
> 
> I'm afraid that assumption is usually false, as you only need to access the
> FLASH when you want to change boot flags or update the boot loader.

At the same time, flash doesn't have to be fast... can't we use a
smaller bounce buffer (a page) and divide the transfer ?

Ben.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
  2007-01-30  9:08             ` Benjamin Herrenschmidt
@ 2007-01-30 10:44               ` Arnd Bergmann
  -1 siblings, 0 replies; 64+ messages in thread
From: Arnd Bergmann @ 2007-01-30 10:44 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Geert Uytterhoeven, linuxppc-dev,
	Linux Frame Buffer Device Development, James Simmons,
	Paul Mackerras

On Tuesday 30 January 2007 10:08, Benjamin Herrenschmidt wrote:
> 
> > I'm afraid that assumption is usually false, as you only need to access the
> > FLASH when you want to change boot flags or update the boot loader.
> 
> At the same time, flash doesn't have to be fast... can't we use a
> smaller bounce buffer (a page) and divide the transfer ?

No, the problem is that the flash interface only supports an hcall
for 'erase+write', but not separately, so the writes need to do
in erase block size, even if the physical medium can probably
handle smaller writes after a block was erased.

	Arnd <><

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
@ 2007-01-30 10:44               ` Arnd Bergmann
  0 siblings, 0 replies; 64+ messages in thread
From: Arnd Bergmann @ 2007-01-30 10:44 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Geert Uytterhoeven, linuxppc-dev,
	Linux Frame Buffer Device Development, James Simmons,
	Paul Mackerras

On Tuesday 30 January 2007 10:08, Benjamin Herrenschmidt wrote:
> 
> > I'm afraid that assumption is usually false, as you only need to access the
> > FLASH when you want to change boot flags or update the boot loader.
> 
> At the same time, flash doesn't have to be fast... can't we use a
> smaller bounce buffer (a page) and divide the transfer ?

No, the problem is that the flash interface only supports an hcall
for 'erase+write', but not separately, so the writes need to do
in erase block size, even if the physical medium can probably
handle smaller writes after a block was erased.

	Arnd <><

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-29 16:15         ` Christoph Hellwig
  (?)
  (?)
@ 2007-01-30 18:39         ` Segher Boessenkool
  2007-01-30 19:39             ` Geert Uytterhoeven
  2007-01-31  8:45             ` Christoph Hellwig
  -1 siblings, 2 replies; 64+ messages in thread
From: Segher Boessenkool @ 2007-01-30 18:39 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Geert Uytterhoeven, Linux Frame Buffer Device Development,
	Paul Mackerras, James Simmons, Linux/PPC Development

>> We can make FB_PS3 (and SND_PS3 later) select PS3_PS3AV. Is that  
>> better?
>> I prefer not to make it unconditional, as people who want to run  
>> their PS3s
>> headless don't need it.
>
> Ok.  Even better would be handling it on the makefile level, by doing
>
> obj-$(CONFIG_FB_PS3)	+= ps3_av.o
> obj-$(CONFIG_SND_PS3)	+= ps3_av.o

I don't think Kbuild will be too happy with that.  Or does
it filter out duplicate files everywhere (dep, build, link)?


Segher

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-30 18:39         ` Segher Boessenkool
@ 2007-01-30 19:39             ` Geert Uytterhoeven
  2007-01-31  8:45             ` Christoph Hellwig
  1 sibling, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-30 19:39 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: James Simmons, Paul Mackerras,
	Linux Frame Buffer Device Development, Christoph Hellwig,
	Linux/PPC Development

On Tue, 30 Jan 2007, Segher Boessenkool wrote:
> >> We can make FB_PS3 (and SND_PS3 later) select PS3_PS3AV. Is that  
> >> better?
> >> I prefer not to make it unconditional, as people who want to run  
> >> their PS3s
> >> headless don't need it.
> >
> > Ok.  Even better would be handling it on the makefile level, by doing
> >
> > obj-$(CONFIG_FB_PS3)	+= ps3_av.o
> > obj-$(CONFIG_SND_PS3)	+= ps3_av.o
> 
> I don't think Kbuild will be too happy with that.  Or does
> it filter out duplicate files everywhere (dep, build, link)?

Yes, it filters out duplicates. But I went for `select' instead.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
@ 2007-01-30 19:39             ` Geert Uytterhoeven
  0 siblings, 0 replies; 64+ messages in thread
From: Geert Uytterhoeven @ 2007-01-30 19:39 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: James Simmons, Paul Mackerras,
	Linux Frame Buffer Device Development, Linux/PPC Development

On Tue, 30 Jan 2007, Segher Boessenkool wrote:
> >> We can make FB_PS3 (and SND_PS3 later) select PS3_PS3AV. Is that  
> >> better?
> >> I prefer not to make it unconditional, as people who want to run  
> >> their PS3s
> >> headless don't need it.
> >
> > Ok.  Even better would be handling it on the makefile level, by doing
> >
> > obj-$(CONFIG_FB_PS3)	+= ps3_av.o
> > obj-$(CONFIG_SND_PS3)	+= ps3_av.o
> 
> I don't think Kbuild will be too happy with that.  Or does
> it filter out duplicate files everywhere (dep, build, link)?

Yes, it filters out duplicates. But I went for `select' instead.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE)
Geert.Uytterhoeven@sonycom.com ------- The Corporate Village, Da Vincilaan 7-D1
Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
  2007-01-30  8:16       ` Geert Uytterhoeven
@ 2007-01-30 22:37         ` Michael Ellerman
  -1 siblings, 0 replies; 64+ messages in thread
From: Michael Ellerman @ 2007-01-30 22:37 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development


[-- Attachment #1.1: Type: text/plain, Size: 1490 bytes --]

On Tue, 2007-01-30 at 09:16 +0100, Geert Uytterhoeven wrote:
> On Tue, 30 Jan 2007, Michael Ellerman wrote:
> > On Thu, 2007-01-25 at 18:50 +0100, Geert Uytterhoeven wrote:
> > > Preallocate bootmem memory for the PS3 frame buffer device, which needs a
> > > large block of physically-contiguous memory. The size of this memory block is
> > > configurable:
> > >   - The config option CONFIG_FB_PS3_DEFAULT_SIZE_M allows to specify the
> > >     default amount of memory (in MiB) allocated to the virtual frame buffer.
> > >   - The early boot parameter `ps3fb=xxx' allows to override the default value.
> > >     It will be rounded up to a multiple of 1 MiB, if needed.
> > > 
> > > Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> > > Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
> > 
> > Rather than doing the alloc in setup.c, defining a structure to the hold
> > the params, and then exporting the structure - why don't you just do the
> > alloc in the ps3 fb driver code, and have it all private in there?
> 
> Because at that time it's no longer possible to allocate such a big block of
> memory.

When it's built as a module, yeah I thought you'd say that. Oh well.

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

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

[-- Attachment #2: Type: text/plain, Size: 146 bytes --]

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb
@ 2007-01-30 22:37         ` Michael Ellerman
  0 siblings, 0 replies; 64+ messages in thread
From: Michael Ellerman @ 2007-01-30 22:37 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Paul Mackerras, James Simmons,
	Linux Frame Buffer Device Development, Linux/PPC Development

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

On Tue, 2007-01-30 at 09:16 +0100, Geert Uytterhoeven wrote:
> On Tue, 30 Jan 2007, Michael Ellerman wrote:
> > On Thu, 2007-01-25 at 18:50 +0100, Geert Uytterhoeven wrote:
> > > Preallocate bootmem memory for the PS3 frame buffer device, which needs a
> > > large block of physically-contiguous memory. The size of this memory block is
> > > configurable:
> > >   - The config option CONFIG_FB_PS3_DEFAULT_SIZE_M allows to specify the
> > >     default amount of memory (in MiB) allocated to the virtual frame buffer.
> > >   - The early boot parameter `ps3fb=xxx' allows to override the default value.
> > >     It will be rounded up to a multiple of 1 MiB, if needed.
> > > 
> > > Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> > > Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
> > 
> > Rather than doing the alloc in setup.c, defining a structure to the hold
> > the params, and then exporting the structure - why don't you just do the
> > alloc in the ps3 fb driver code, and have it all private in there?
> 
> Because at that time it's no longer possible to allocate such a big block of
> memory.

When it's built as a module, yeah I thought you'd say that. Oh well.

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
  2007-01-30 18:39         ` Segher Boessenkool
@ 2007-01-31  8:45             ` Christoph Hellwig
  2007-01-31  8:45             ` Christoph Hellwig
  1 sibling, 0 replies; 64+ messages in thread
From: Christoph Hellwig @ 2007-01-31  8:45 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Linux Frame Buffer Device Development, Linux/PPC Development,
	Paul Mackerras, Geert Uytterhoeven, James Simmons,
	Christoph Hellwig

On Tue, Jan 30, 2007 at 07:39:40PM +0100, Segher Boessenkool wrote:
> >obj-$(CONFIG_FB_PS3)	+= ps3_av.o
> >obj-$(CONFIG_SND_PS3)	+= ps3_av.o
> 
> I don't think Kbuild will be too happy with that.  Or does
> it filter out duplicate files everywhere (dep, build, link)?

Yes, it's a feature stamming from the first predecessor of the current
kbuild system (drivers/sound/Makefile in late 2.2.x).

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/9] ps3: AV Settings Driver
@ 2007-01-31  8:45             ` Christoph Hellwig
  0 siblings, 0 replies; 64+ messages in thread
From: Christoph Hellwig @ 2007-01-31  8:45 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Linux Frame Buffer Device Development, Linux/PPC Development,
	Paul Mackerras, Geert Uytterhoeven, James Simmons

On Tue, Jan 30, 2007 at 07:39:40PM +0100, Segher Boessenkool wrote:
> >obj-$(CONFIG_FB_PS3)	+= ps3_av.o
> >obj-$(CONFIG_SND_PS3)	+= ps3_av.o
> 
> I don't think Kbuild will be too happy with that.  Or does
> it filter out duplicate files everywhere (dep, build, link)?

Yes, it's a feature stamming from the first predecessor of the current
kbuild system (drivers/sound/Makefile in late 2.2.x).

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
  2007-01-26  3:14   ` Christoph Hellwig
  2007-01-30  2:23       ` Michael Ellerman
@ 2007-03-24 23:46     ` Geoff Levand
  2007-03-25 17:43       ` Milton Miller
  2007-03-27 17:35       ` Christoph Hellwig
  1 sibling, 2 replies; 64+ messages in thread
From: Geoff Levand @ 2007-03-24 23:46 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Geert Uytterhoeven, Linux/PPC Development, Paul Mackerras

Christoph Hellwig wrote:
>>>  static void ps3_hpte_clear(void)
>>  {
>> +
>> +#ifdef CONFIG_FB_PS3
>> +	ps3fb_cleanup();
>> +#endif
> 
> And well, adding framebuffer calls into the mmu code is rather fucked.
> This at least needs a big comment explaning the hypervisor braindamage
> that is responsible for this in colourfull language.

Sorry for such a late reply, but I'm now doing the kexec code and see
why it was put here (by the original author).  It is so you will have
debugging output until the very last possible moment during a kexec
shutdown.

The real problem is really that this routine (and the corresponding ppc_md
variable) are inappropriately named.  In the general case all that is left
to do is to call ppc_md.hpte_clear_all, but for ps3 we also want to do the
framebuffer shutdown here, so something like this should be better:

-static void ps3_hpte_clear(void)
+static void ps3_kexec_final(void)

-	ppc_md.hpte_clear_all = ps3_hpte_clear;
+	ppc_md.hpte_clear_all = ps3_kexec_final;

-Geoff

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
  2007-03-24 23:46     ` Geoff Levand
@ 2007-03-25 17:43       ` Milton Miller
  2007-03-27  1:06         ` Geoff Levand
  2007-03-27 17:35       ` Christoph Hellwig
  1 sibling, 1 reply; 64+ messages in thread
From: Milton Miller @ 2007-03-25 17:43 UTC (permalink / raw)
  To: Geoff Levand; +Cc: linuxppc-dev, Paul Mackerras


Paul, after reading this note I send a big fat

NACK

to this patch.

On Mar 24, 2007, at 6:46 PM, Geoff Levand wrote:

> Christoph Hellwig wrote:
>>>>  static void ps3_hpte_clear(void)
>>>  {
>>> +
>>> +#ifdef CONFIG_FB_PS3
>>> +    ps3fb_cleanup();
>>> +#endif
>>
>> And well, adding framebuffer calls into the mmu code is rather fucked.
>> This at least needs a big comment explaning the hypervisor braindamage
>> that is responsible for this in colourfull language.
>
> Sorry for such a late reply, but I'm now doing the kexec code and see
> why it was put here (by the original author).  It is so you will have
> debugging output until the very last possible moment during a kexec
> shutdown.

But that is REALLY to late for that.

> The real problem is really that this routine (and the corresponding 
> ppc_md
> variable) are inappropriately named.

Ok, this should be
ppc_md.kexec_cleanup_nothing_but_static_data_bss_real_mode_cleanup()


> In the general case all that is left
> to do is to call ppc_md.hpte_clear_all, but for ps3 we also want to do 
> the
> framebuffer shutdown here, so something like this should be better:
>
> -static void ps3_hpte_clear(void)
> +static void ps3_kexec_final(void)
>
> -       ppc_md.hpte_clear_all = ps3_hpte_clear;
> +       ppc_md.hpte_clear_all = ps3_kexec_final;
>

NACK.

Because at this point, we have already done the copy of the new kernel
to its kexec-specified location, and we are in real mode.   There is
no way ps3fb_cleanup should be running that late.

The only thing ppc_md.htpe_clear_all is allowed to touch is data built
into vmlinux (that is, static data and bss, not even per-cpu data).

Actually, it can touch tce tables, the hash table, and rtas, but only if
they are below the real mode limit.   That's because those regions are 
also
protected from overwrite by default_machine_kexec_prepare().   You 
could use
that hook to protect your fb allocation, but then you need to (1) export
the range to the device tree for kexec user space and (2) change 
kexec-tools
to look for this region.


You could use machine_kexec and machine_crash_kexec, but I would just 
use
the kexec_cpu_down (its called with primary=1 last).

There shouldn't be any debugging after cpu_down anways.  The only things
left are switch stacks, copy kernel, and call htpe_clear.

Oh, I just looked at your ps3 kexec hooks.  Your ps3_kexec_cpu_down 
looks
totally broken.  kexec_cpu_down(crash, secondary) is called on each
cpu, so there should be no for_each_cpu loops there.  Also, the primary
cpu is likely not cpu 0, although it will be called last, after the
other cpus are offline spinning.

If your platform requires you to be on a given cpu you should
set_tasks_allowed() in your machine_kexec_*shutdown, but that will have
an negative effect on crash reliability.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
  2007-03-25 17:43       ` Milton Miller
@ 2007-03-27  1:06         ` Geoff Levand
  0 siblings, 0 replies; 64+ messages in thread
From: Geoff Levand @ 2007-03-27  1:06 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras

Milton Miller wrote:
> Paul, after reading this note I send a big fat
> 
> NACK
> 
> to this patch.

Sorry for not being more clear.  That was what I was kind of
saying, that there is something strange here, and I am looking
into it.

> On Mar 24, 2007, at 6:46 PM, Geoff Levand wrote:
> 
>> Christoph Hellwig wrote:
>>>>>  static void ps3_hpte_clear(void)
>>>>  {
>>>> +
>>>> +#ifdef CONFIG_FB_PS3
>>>> +    ps3fb_cleanup();
>>>> +#endif
>>>
>>> And well, adding framebuffer calls into the mmu code is rather fucked.
>>> This at least needs a big comment explaning the hypervisor braindamage
>>> that is responsible for this in colourfull language.
>>
>> Sorry for such a late reply, but I'm now doing the kexec code and see
>> why it was put here (by the original author).  It is so you will have
>> debugging output until the very last possible moment during a kexec
>> shutdown.
> 
> But that is REALLY to late for that.
> 
>> The real problem is really that this routine (and the corresponding 
>> ppc_md
>> variable) are inappropriately named.
> 
> Ok, this should be
> ppc_md.kexec_cleanup_nothing_but_static_data_bss_real_mode_cleanup()
> 
> 
>> In the general case all that is left
>> to do is to call ppc_md.hpte_clear_all, but for ps3 we also want to do 
>> the
>> framebuffer shutdown here, so something like this should be better:
>>
>> -static void ps3_hpte_clear(void)
>> +static void ps3_kexec_final(void)
>>
>> -       ppc_md.hpte_clear_all = ps3_hpte_clear;
>> +       ppc_md.hpte_clear_all = ps3_kexec_final;
>>
> 
> NACK.

Yes, I just wanted to report why this strange code was in ps3_hpte_clear,
since Christoph never did get an answer, and give my idea on what might
work.  This is not a solution, just a thought.  I haven't really got
into it enough to say what the best way would be.  Thanks for the
comments though.
 
> Oh, I just looked at your ps3 kexec hooks.  Your ps3_kexec_cpu_down 
> looks
> totally broken.  

Yes, disregard anything you find regarding kexec on ps3.  I'll post
some new stuff for review, hopefully sometime soon.

-Geoff

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE
  2007-03-24 23:46     ` Geoff Levand
  2007-03-25 17:43       ` Milton Miller
@ 2007-03-27 17:35       ` Christoph Hellwig
  1 sibling, 0 replies; 64+ messages in thread
From: Christoph Hellwig @ 2007-03-27 17:35 UTC (permalink / raw)
  To: Geoff Levand; +Cc: Geert Uytterhoeven, Linux/PPC Development, Paul Mackerras

On Sat, Mar 24, 2007 at 04:46:41PM -0700, Geoff Levand wrote:
> Sorry for such a late reply, but I'm now doing the kexec code and see
> why it was put here (by the original author).  It is so you will have
> debugging output until the very last possible moment during a kexec
> shutdown.
> 
> The real problem is really that this routine (and the corresponding ppc_md
> variable) are inappropriately named.  In the general case all that is left
> to do is to call ppc_md.hpte_clear_all, but for ps3 we also want to do the
> framebuffer shutdown here, so something like this should be better:
> 
> -static void ps3_hpte_clear(void)
> +static void ps3_kexec_final(void)
> 
> -	ppc_md.hpte_clear_all = ps3_hpte_clear;
> +	ppc_md.hpte_clear_all = ps3_kexec_final;

as a start method calls sould always be be driver/arch_methodname,
so ps3_hpte_clear_all here, not ps3_hpte_clear but not ps3_kexec_final
either unless the method name changes.

I think you got this code rejected by someone who knows a lot more about
kexec than me, but in a case where something this odd would be allowed
it should at least have a big comment explaining what's going on here.
(In this case it would be basically the content of your email)

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2007-03-27 17:35 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-25 17:46 [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
2007-01-25 17:48 ` [PATCH 1/9] ps3: AV Settings Driver Geert Uytterhoeven
2007-01-25 17:48   ` Geert Uytterhoeven
2007-01-26  3:12   ` Christoph Hellwig
2007-01-29 14:10     ` Geert Uytterhoeven
2007-01-29 14:10       ` Geert Uytterhoeven
2007-01-29 16:15       ` Christoph Hellwig
2007-01-29 16:15         ` Christoph Hellwig
2007-01-29 19:24         ` Geoff Levand
2007-01-30 18:39         ` Segher Boessenkool
2007-01-30 19:39           ` Geert Uytterhoeven
2007-01-30 19:39             ` Geert Uytterhoeven
2007-01-31  8:45           ` Christoph Hellwig
2007-01-31  8:45             ` Christoph Hellwig
2007-01-26  4:13   ` Arnd Bergmann
2007-01-26 14:56     ` Geert Uytterhoeven
2007-01-26 14:56       ` Geert Uytterhoeven
2007-01-28 21:37       ` Benjamin Herrenschmidt
2007-01-28 21:37         ` Benjamin Herrenschmidt
2007-01-29 15:14     ` Geert Uytterhoeven
2007-01-29 15:14       ` Geert Uytterhoeven
2007-01-30  0:16       ` Arnd Bergmann
2007-01-30  0:16         ` Arnd Bergmann
2007-01-25 17:48 ` [PATCH 2/9] fbdev modedb: allow refresh rates for named video modes Geert Uytterhoeven
2007-01-25 17:48   ` Geert Uytterhoeven
2007-01-25 17:49 ` [PATCH 3/9] fbdev modedb: make more pointer parameters const Geert Uytterhoeven
2007-01-25 17:49   ` Geert Uytterhoeven
2007-01-25 17:49 ` [PATCH 4/9] fb_videomode_to_var: reset virtual screen parameters Geert Uytterhoeven
2007-01-25 17:49   ` Geert Uytterhoeven
2007-01-25 17:50 ` [PATCH 5/9] ps3: Preallocate bootmem memory for ps3fb Geert Uytterhoeven
2007-01-25 17:50   ` Geert Uytterhoeven
2007-01-30  2:29   ` Michael Ellerman
2007-01-30  2:29     ` Michael Ellerman
2007-01-30  8:16     ` Geert Uytterhoeven
2007-01-30  8:16       ` Geert Uytterhoeven
2007-01-30  8:27       ` Arnd Bergmann
2007-01-30  8:27         ` Arnd Bergmann
2007-01-30  8:36         ` Geert Uytterhoeven
2007-01-30  8:36           ` Geert Uytterhoeven
2007-01-30  9:08           ` Benjamin Herrenschmidt
2007-01-30  9:08             ` Benjamin Herrenschmidt
2007-01-30 10:44             ` Arnd Bergmann
2007-01-30 10:44               ` Arnd Bergmann
2007-01-30 22:37       ` Michael Ellerman
2007-01-30 22:37         ` Michael Ellerman
2007-01-25 17:50 ` [PATCH 6/9] ps3: Virtual Frame Buffer Driver Geert Uytterhoeven
2007-01-25 17:50   ` Geert Uytterhoeven
2007-01-25 21:36   ` [Linux-fbdev-devel] " Bernhard Fischer
2007-01-25 17:51 ` [PATCH 7/9] ps3: disable display flipping during mode changes Geert Uytterhoeven
2007-01-25 17:51   ` Geert Uytterhoeven
2007-01-26  2:13   ` Arnd Bergmann
2007-01-25 17:51 ` [PATCH 8/9] ps3: cleanup ps3fb before clearing HPTE Geert Uytterhoeven
2007-01-25 17:51   ` Geert Uytterhoeven
2007-01-26  3:14   ` Christoph Hellwig
2007-01-30  2:23     ` Michael Ellerman
2007-01-30  2:23       ` Michael Ellerman
2007-03-24 23:46     ` Geoff Levand
2007-03-25 17:43       ` Milton Miller
2007-03-27  1:06         ` Geoff Levand
2007-03-27 17:35       ` Christoph Hellwig
2007-01-25 17:52 ` [PATCH 9/9] ps3: ps3av/fb defconfig updates Geert Uytterhoeven
2007-01-25 17:52   ` Geert Uytterhoeven
2007-01-25 17:55 ` [PATCH 0/9] ps3av/fb drivers for 2.6.21 Geert Uytterhoeven
2007-01-25 17:55   ` Geert Uytterhoeven

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.