diff options
| -rw-r--r-- | drivers/media/pci/ivtv/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/media/pci/ivtv/ivtvfb.c | 58 |
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) | |||
| 1099 | static int ivtvfb_init_io(struct ivtv *itv) | 1098 | static 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); |
