aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/pci/ivtv/Kconfig3
-rw-r--r--drivers/media/pci/ivtv/ivtvfb.c58
2 files changed, 26 insertions, 35 deletions
diff --git a/drivers/media/pci/ivtv/Kconfig b/drivers/media/pci/ivtv/Kconfig
index dd6ee57e3a4c..6e5867c57305 100644
--- a/drivers/media/pci/ivtv/Kconfig
+++ b/drivers/media/pci/ivtv/Kconfig
@@ -57,5 +57,8 @@ config VIDEO_FB_IVTV
57 This is used in the Hauppauge PVR-350 card. There is a driver 57 This is used in the Hauppauge PVR-350 card. There is a driver
58 homepage at <http://www.ivtvdriver.org>. 58 homepage at <http://www.ivtvdriver.org>.
59 59
60 In order to use this module, you will need to boot with PAT disabled
61 on x86 systems, using the nopat kernel parameter.
62
60 To compile this driver as a module, choose M here: the 63 To compile this driver as a module, choose M here: the
61 module will be called ivtvfb. 64 module will be called ivtvfb.
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
index 9ff1230192e8..4cb365d4ffdc 100644
--- a/drivers/media/pci/ivtv/ivtvfb.c
+++ b/drivers/media/pci/ivtv/ivtvfb.c
@@ -44,8 +44,8 @@
44#include <linux/ivtvfb.h> 44#include <linux/ivtvfb.h>
45#include <linux/slab.h> 45#include <linux/slab.h>
46 46
47#ifdef CONFIG_MTRR 47#ifdef CONFIG_X86_64
48#include <asm/mtrr.h> 48#include <asm/pat.h>
49#endif 49#endif
50 50
51#include "ivtv-driver.h" 51#include "ivtv-driver.h"
@@ -155,12 +155,11 @@ struct osd_info {
155 /* Buffer size */ 155 /* Buffer size */
156 u32 video_buffer_size; 156 u32 video_buffer_size;
157 157
158#ifdef CONFIG_MTRR
159 /* video_base rounded down as required by hardware MTRRs */ 158 /* video_base rounded down as required by hardware MTRRs */
160 unsigned long fb_start_aligned_physaddr; 159 unsigned long fb_start_aligned_physaddr;
161 /* video_base rounded up as required by hardware MTRRs */ 160 /* video_base rounded up as required by hardware MTRRs */
162 unsigned long fb_end_aligned_physaddr; 161 unsigned long fb_end_aligned_physaddr;
163#endif 162 int wc_cookie;
164 163
165 /* Store the buffer offset */ 164 /* Store the buffer offset */
166 int set_osd_coords_x; 165 int set_osd_coords_x;
@@ -1099,6 +1098,8 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
1099static int ivtvfb_init_io(struct ivtv *itv) 1098static int ivtvfb_init_io(struct ivtv *itv)
1100{ 1099{
1101 struct osd_info *oi = itv->osd_info; 1100 struct osd_info *oi = itv->osd_info;
1101 /* Find the largest power of two that maps the whole buffer */
1102 int size_shift = 31;
1102 1103
1103 mutex_lock(&itv->serialize_lock); 1104 mutex_lock(&itv->serialize_lock);
1104 if (ivtv_init_on_first_open(itv)) { 1105 if (ivtv_init_on_first_open(itv)) {
@@ -1132,29 +1133,16 @@ static int ivtvfb_init_io(struct ivtv *itv)
1132 oi->video_pbase, oi->video_vbase, 1133 oi->video_pbase, oi->video_vbase,
1133 oi->video_buffer_size / 1024); 1134 oi->video_buffer_size / 1024);
1134 1135
1135#ifdef CONFIG_MTRR 1136 while (!(oi->video_buffer_size & (1 << size_shift)))
1136 { 1137 size_shift--;
1137 /* Find the largest power of two that maps the whole buffer */ 1138 size_shift++;
1138 int size_shift = 31; 1139 oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1139 1140 oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1140 while (!(oi->video_buffer_size & (1 << size_shift))) { 1141 oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1141 size_shift--; 1142 oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1142 } 1143 oi->wc_cookie = arch_phys_wc_add(oi->fb_start_aligned_physaddr,
1143 size_shift++; 1144 oi->fb_end_aligned_physaddr -
1144 oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1); 1145 oi->fb_start_aligned_physaddr);
1145 oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1146 oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1147 oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1148 if (mtrr_add(oi->fb_start_aligned_physaddr,
1149 oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
1150 MTRR_TYPE_WRCOMB, 1) < 0) {
1151 IVTVFB_INFO("disabled mttr\n");
1152 oi->fb_start_aligned_physaddr = 0;
1153 oi->fb_end_aligned_physaddr = 0;
1154 }
1155 }
1156#endif
1157
1158 /* Blank the entire osd. */ 1146 /* Blank the entire osd. */
1159 memset_io(oi->video_vbase, 0, oi->video_buffer_size); 1147 memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1160 1148
@@ -1172,14 +1160,7 @@ static void ivtvfb_release_buffers (struct ivtv *itv)
1172 1160
1173 /* Release pseudo palette */ 1161 /* Release pseudo palette */
1174 kfree(oi->ivtvfb_info.pseudo_palette); 1162 kfree(oi->ivtvfb_info.pseudo_palette);
1175 1163 arch_phys_wc_del(oi->wc_cookie);
1176#ifdef CONFIG_MTRR
1177 if (oi->fb_end_aligned_physaddr) {
1178 mtrr_del(-1, oi->fb_start_aligned_physaddr,
1179 oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
1180 }
1181#endif
1182
1183 kfree(oi); 1164 kfree(oi);
1184 itv->osd_info = NULL; 1165 itv->osd_info = NULL;
1185} 1166}
@@ -1284,6 +1265,13 @@ static int __init ivtvfb_init(void)
1284 int registered = 0; 1265 int registered = 0;
1285 int err; 1266 int err;
1286 1267
1268#ifdef CONFIG_X86_64
1269 if (WARN(pat_enabled(),
1270 "ivtvfb needs PAT disabled, boot with nopat kernel parameter\n")) {
1271 return -ENODEV;
1272 }
1273#endif
1274
1287 if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) { 1275 if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1288 printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n", 1276 printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1289 IVTV_MAX_CARDS - 1); 1277 IVTV_MAX_CARDS - 1);