* [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),
+ ¶m->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(¶m->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),
+ ¶m->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(¶m->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.