linux/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012-15 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include <linux/slab.h>
  27
  28#include "dm_services.h"
  29#include "basics/conversion.h"
  30
  31#include "dce_opp.h"
  32
  33#include "reg_helper.h"
  34
  35#define REG(reg)\
  36        (opp110->regs->reg)
  37
  38#undef FN
  39#define FN(reg_name, field_name) \
  40        opp110->opp_shift->field_name, opp110->opp_mask->field_name
  41
  42#define CTX \
  43        opp110->base.ctx
  44
  45enum {
  46        MAX_PWL_ENTRY = 128,
  47        MAX_REGIONS_NUMBER = 16
  48};
  49
  50enum {
  51        MAX_LUT_ENTRY = 256,
  52        MAX_NUMBER_OF_ENTRIES = 256
  53};
  54
  55
  56enum {
  57        OUTPUT_CSC_MATRIX_SIZE = 12
  58};
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81/*
  82 *****************************************************************************
  83 *  Function: regamma_config_regions_and_segments
  84 *
  85 *     build regamma curve by using predefined hw points
  86 *     uses interface parameters ,like EDID coeff.
  87 *
  88 * @param   : parameters   interface parameters
  89 *  @return void
  90 *
  91 *  @note
  92 *
  93 *  @see
  94 *
  95 *****************************************************************************
  96 */
  97
  98
  99
 100/**
 101 *      set_truncation
 102 *      1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
 103 *      2) enable truncation
 104 *      3) HW remove 12bit FMT support for DCE11 power saving reason.
 105 */
 106static void set_truncation(
 107                struct dce110_opp *opp110,
 108                const struct bit_depth_reduction_params *params)
 109{
 110        /*Disable truncation*/
 111        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 112                        FMT_TRUNCATE_EN, 0,
 113                        FMT_TRUNCATE_DEPTH, 0,
 114                        FMT_TRUNCATE_MODE, 0);
 115
 116
 117        if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
 118                /*  8bpc trunc on YCbCr422*/
 119                if (params->flags.TRUNCATE_DEPTH == 1)
 120                        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 121                                        FMT_TRUNCATE_EN, 1,
 122                                        FMT_TRUNCATE_DEPTH, 1,
 123                                        FMT_TRUNCATE_MODE, 0);
 124                else if (params->flags.TRUNCATE_DEPTH == 2)
 125                        /*  10bpc trunc on YCbCr422*/
 126                        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 127                                        FMT_TRUNCATE_EN, 1,
 128                                        FMT_TRUNCATE_DEPTH, 2,
 129                                        FMT_TRUNCATE_MODE, 0);
 130                return;
 131        }
 132        /* on other format-to do */
 133        if (params->flags.TRUNCATE_ENABLED == 0)
 134                return;
 135        /*Set truncation depth and Enable truncation*/
 136        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 137                                FMT_TRUNCATE_EN, 1,
 138                                FMT_TRUNCATE_DEPTH,
 139                                params->flags.TRUNCATE_DEPTH,
 140                                FMT_TRUNCATE_MODE,
 141                                params->flags.TRUNCATE_MODE);
 142}
 143
 144
 145/**
 146 *      set_spatial_dither
 147 *      1) set spatial dithering mode: pattern of seed
 148 *      2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp
 149 *      3) set random seed
 150 *      4) set random mode
 151 *              lfsr is reset every frame or not reset
 152 *              RGB dithering method
 153 *              0: RGB data are all dithered with x^28+x^3+1
 154 *              1: R data is dithered with x^28+x^3+1
 155 *              G data is dithered with x^28+X^9+1
 156 *              B data is dithered with x^28+x^13+1
 157 *              enable high pass filter or not
 158 *      5) enable spatical dithering
 159 */
 160static void set_spatial_dither(
 161        struct dce110_opp *opp110,
 162        const struct bit_depth_reduction_params *params)
 163{
 164        /*Disable spatial (random) dithering*/
 165        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 166                FMT_SPATIAL_DITHER_EN, 0,
 167                FMT_SPATIAL_DITHER_DEPTH, 0,
 168                FMT_SPATIAL_DITHER_MODE, 0);
 169
 170        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 171                FMT_HIGHPASS_RANDOM_ENABLE, 0,
 172                FMT_FRAME_RANDOM_ENABLE, 0,
 173                FMT_RGB_RANDOM_ENABLE, 0);
 174
 175        REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
 176                FMT_TEMPORAL_DITHER_EN, 0);
 177
 178        /* no 10bpc on DCE11*/
 179        if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
 180                params->flags.SPATIAL_DITHER_DEPTH == 2)
 181                return;
 182
 183        /* only use FRAME_COUNTER_MAX if frameRandom == 1*/
 184
 185        if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX &&
 186                        opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) {
 187                if (params->flags.FRAME_RANDOM == 1) {
 188                        if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
 189                        params->flags.SPATIAL_DITHER_DEPTH == 1) {
 190                                REG_UPDATE_2(FMT_CONTROL,
 191                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
 192                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
 193                        } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
 194                                REG_UPDATE_2(FMT_CONTROL,
 195                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
 196                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
 197                        } else
 198                                return;
 199                } else {
 200                        REG_UPDATE_2(FMT_CONTROL,
 201                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
 202                                        FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
 203                }
 204        }
 205        /* Set seed for random values for
 206         * spatial dithering for R,G,B channels
 207         */
 208        REG_UPDATE(FMT_DITHER_RAND_R_SEED,
 209                        FMT_RAND_R_SEED, params->r_seed_value);
 210
 211        REG_UPDATE(FMT_DITHER_RAND_G_SEED,
 212                        FMT_RAND_G_SEED, params->g_seed_value);
 213
 214        REG_UPDATE(FMT_DITHER_RAND_B_SEED,
 215                        FMT_RAND_B_SEED, params->b_seed_value);
 216
 217        /* FMT_OFFSET_R_Cr  31:16 0x0 Setting the zero
 218         * offset for the R/Cr channel, lower 4LSB
 219         * is forced to zeros. Typically set to 0
 220         * RGB and 0x80000 YCbCr.
 221         */
 222        /* FMT_OFFSET_G_Y   31:16 0x0 Setting the zero
 223         * offset for the G/Y  channel, lower 4LSB is
 224         * forced to zeros. Typically set to 0 RGB
 225         * and 0x80000 YCbCr.
 226         */
 227        /* FMT_OFFSET_B_Cb  31:16 0x0 Setting the zero
 228         * offset for the B/Cb channel, lower 4LSB is
 229         * forced to zeros. Typically set to 0 RGB and
 230         * 0x80000 YCbCr.
 231         */
 232
 233        /* Disable High pass filter
 234         * Reset only at startup
 235         * Set RGB data dithered with x^28+x^3+1
 236         */
 237        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 238                FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
 239                FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
 240                FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
 241
 242        /* Set spatial dithering bit depth
 243         * Set spatial dithering mode
 244         * (default is Seed patterrn AAAA...)
 245         * Enable spatial dithering
 246         */
 247        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 248                FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
 249                FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
 250                FMT_SPATIAL_DITHER_EN, 1);
 251}
 252
 253/**
 254 *      SetTemporalDither (Frame Modulation)
 255 *      1) set temporal dither depth
 256 *      2) select pattern: from hard-coded pattern or programmable pattern
 257 *      3) select optimized strips for BGR or RGB LCD sub-pixel
 258 *      4) set s matrix
 259 *      5) set t matrix
 260 *      6) set grey level for 0.25, 0.5, 0.75
 261 *      7) enable temporal dithering
 262 */
 263
 264static void set_temporal_dither(
 265        struct dce110_opp *opp110,
 266        const struct bit_depth_reduction_params *params)
 267{
 268        /*Disable temporal (frame modulation) dithering first*/
 269        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 270                FMT_TEMPORAL_DITHER_EN, 0,
 271                FMT_TEMPORAL_DITHER_RESET, 0,
 272                FMT_TEMPORAL_DITHER_OFFSET, 0);
 273
 274        REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
 275                FMT_TEMPORAL_DITHER_DEPTH, 0,
 276                FMT_TEMPORAL_LEVEL, 0);
 277
 278        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 279                FMT_25FRC_SEL, 0,
 280                FMT_50FRC_SEL, 0,
 281                FMT_75FRC_SEL, 0);
 282
 283        /* no 10bpc dither on DCE11*/
 284        if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
 285                params->flags.FRAME_MODULATION_DEPTH == 2)
 286                return;
 287
 288        /* Set temporal dithering depth*/
 289        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 290                FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH,
 291                FMT_TEMPORAL_DITHER_RESET, 0,
 292                FMT_TEMPORAL_DITHER_OFFSET, 0);
 293
 294        /*Select legacy pattern based on FRC and Temporal level*/
 295        if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) {
 296                REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0);
 297                /*Set s matrix*/
 298                REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0);
 299                /*Set t matrix*/
 300                REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0);
 301        }
 302
 303        /*Select patterns for 0.25, 0.5 and 0.75 grey level*/
 304        REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
 305                FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL);
 306
 307        REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
 308                FMT_25FRC_SEL, params->flags.FRC25,
 309                FMT_50FRC_SEL, params->flags.FRC50,
 310                FMT_75FRC_SEL, params->flags.FRC75);
 311
 312        /*Enable bit reduction by temporal (frame modulation) dithering*/
 313        REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
 314                FMT_TEMPORAL_DITHER_EN, 1);
 315}
 316
 317/**
 318 *      Set Clamping
 319 *      1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
 320 *              1 for 8 bpc
 321 *              2 for 10 bpc
 322 *              3 for 12 bpc
 323 *              7 for programable
 324 *      2) Enable clamp if Limited range requested
 325 */
 326void dce110_opp_set_clamping(
 327        struct dce110_opp *opp110,
 328        const struct clamping_and_pixel_encoding_params *params)
 329{
 330        REG_SET_2(FMT_CLAMP_CNTL, 0,
 331                FMT_CLAMP_DATA_EN, 0,
 332                FMT_CLAMP_COLOR_FORMAT, 0);
 333
 334        switch (params->clamping_level) {
 335        case CLAMPING_FULL_RANGE:
 336                break;
 337        case CLAMPING_LIMITED_RANGE_8BPC:
 338                REG_SET_2(FMT_CLAMP_CNTL, 0,
 339                        FMT_CLAMP_DATA_EN, 1,
 340                        FMT_CLAMP_COLOR_FORMAT, 1);
 341                break;
 342        case CLAMPING_LIMITED_RANGE_10BPC:
 343                REG_SET_2(FMT_CLAMP_CNTL, 0,
 344                        FMT_CLAMP_DATA_EN, 1,
 345                        FMT_CLAMP_COLOR_FORMAT, 2);
 346                break;
 347        case CLAMPING_LIMITED_RANGE_12BPC:
 348                REG_SET_2(FMT_CLAMP_CNTL, 0,
 349                        FMT_CLAMP_DATA_EN, 1,
 350                        FMT_CLAMP_COLOR_FORMAT, 3);
 351                break;
 352        case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
 353                /*Set clamp control*/
 354                REG_SET_2(FMT_CLAMP_CNTL, 0,
 355                        FMT_CLAMP_DATA_EN, 1,
 356                        FMT_CLAMP_COLOR_FORMAT, 7);
 357
 358                /*set the defaults*/
 359                REG_SET_2(FMT_CLAMP_COMPONENT_R, 0,
 360                        FMT_CLAMP_LOWER_R, 0x10,
 361                        FMT_CLAMP_UPPER_R, 0xFEF);
 362
 363                REG_SET_2(FMT_CLAMP_COMPONENT_G, 0,
 364                        FMT_CLAMP_LOWER_G, 0x10,
 365                        FMT_CLAMP_UPPER_G, 0xFEF);
 366
 367                REG_SET_2(FMT_CLAMP_COMPONENT_B, 0,
 368                        FMT_CLAMP_LOWER_B, 0x10,
 369                        FMT_CLAMP_UPPER_B, 0xFEF);
 370                break;
 371        default:
 372                break;
 373        }
 374}
 375
 376/**
 377 *      set_pixel_encoding
 378 *
 379 *      Set Pixel Encoding
 380 *              0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
 381 *              1: YCbCr 4:2:2
 382 */
 383static void set_pixel_encoding(
 384        struct dce110_opp *opp110,
 385        const struct clamping_and_pixel_encoding_params *params)
 386{
 387        if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
 388                REG_UPDATE_3(FMT_CONTROL,
 389                                FMT_PIXEL_ENCODING, 0,
 390                                FMT_SUBSAMPLING_MODE, 0,
 391                                FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
 392        else
 393                REG_UPDATE_2(FMT_CONTROL,
 394                                FMT_PIXEL_ENCODING, 0,
 395                                FMT_SUBSAMPLING_MODE, 0);
 396
 397        if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
 398                REG_UPDATE_2(FMT_CONTROL,
 399                                FMT_PIXEL_ENCODING, 1,
 400                                FMT_SUBSAMPLING_ORDER, 0);
 401        }
 402        if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
 403                REG_UPDATE_3(FMT_CONTROL,
 404                                FMT_PIXEL_ENCODING, 2,
 405                                FMT_SUBSAMPLING_MODE, 2,
 406                                FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
 407        }
 408
 409}
 410
 411void dce110_opp_program_bit_depth_reduction(
 412        struct output_pixel_processor *opp,
 413        const struct bit_depth_reduction_params *params)
 414{
 415        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 416
 417        set_truncation(opp110, params);
 418        set_spatial_dither(opp110, params);
 419        set_temporal_dither(opp110, params);
 420}
 421
 422void dce110_opp_program_clamping_and_pixel_encoding(
 423        struct output_pixel_processor *opp,
 424        const struct clamping_and_pixel_encoding_params *params)
 425{
 426        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 427
 428        dce110_opp_set_clamping(opp110, params);
 429        set_pixel_encoding(opp110, params);
 430}
 431
 432static void program_formatter_420_memory(struct output_pixel_processor *opp)
 433{
 434        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 435        uint32_t fmt_mem_cntl_value;
 436
 437        /* Program source select*/
 438        /* Use HW default source select for FMT_MEMORYx_CONTROL */
 439        /* Use that value for FMT_SRC_SELECT as well*/
 440        REG_GET(CONTROL,
 441                        FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value);
 442
 443        REG_UPDATE(FMT_CONTROL,
 444                        FMT_SRC_SELECT, fmt_mem_cntl_value);
 445
 446        /* Turn on the memory */
 447        REG_UPDATE(CONTROL,
 448                        FMT420_MEM0_PWR_FORCE, 0);
 449}
 450
 451void dce110_opp_set_dyn_expansion(
 452        struct output_pixel_processor *opp,
 453        enum dc_color_space color_sp,
 454        enum dc_color_depth color_dpth,
 455        enum signal_type signal)
 456{
 457        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 458
 459        REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
 460                        FMT_DYNAMIC_EXP_EN, 0,
 461                        FMT_DYNAMIC_EXP_MODE, 0);
 462
 463        /*00 - 10-bit -> 12-bit dynamic expansion*/
 464        /*01 - 8-bit  -> 12-bit dynamic expansion*/
 465        if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
 466                signal == SIGNAL_TYPE_DISPLAY_PORT ||
 467                signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
 468                switch (color_dpth) {
 469                case COLOR_DEPTH_888:
 470                        REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
 471                                FMT_DYNAMIC_EXP_EN, 1,
 472                                FMT_DYNAMIC_EXP_MODE, 1);
 473                        break;
 474                case COLOR_DEPTH_101010:
 475                        REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
 476                                FMT_DYNAMIC_EXP_EN, 1,
 477                                FMT_DYNAMIC_EXP_MODE, 0);
 478                        break;
 479                case COLOR_DEPTH_121212:
 480                        REG_UPDATE_2(
 481                                FMT_DYNAMIC_EXP_CNTL,
 482                                FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/
 483                                FMT_DYNAMIC_EXP_MODE, 0);
 484                        break;
 485                default:
 486                        break;
 487                }
 488        }
 489}
 490
 491static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
 492{
 493        struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
 494
 495        /* clear previous phase lock status*/
 496        REG_UPDATE(FMT_CONTROL,
 497                        FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1);
 498
 499        /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
 500        REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10);
 501
 502}
 503
 504void dce110_opp_program_fmt(
 505        struct output_pixel_processor *opp,
 506        struct bit_depth_reduction_params *fmt_bit_depth,
 507        struct clamping_and_pixel_encoding_params *clamping)
 508{
 509        /* dithering is affected by <CrtcSourceSelect>, hence should be
 510         * programmed afterwards */
 511
 512        if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 513                program_formatter_420_memory(opp);
 514
 515        dce110_opp_program_bit_depth_reduction(
 516                opp,
 517                fmt_bit_depth);
 518
 519        dce110_opp_program_clamping_and_pixel_encoding(
 520                opp,
 521                clamping);
 522
 523        if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 524                program_formatter_reset_dig_resync_fifo(opp);
 525
 526        return;
 527}
 528
 529
 530
 531
 532
 533/*****************************************/
 534/* Constructor, Destructor               */
 535/*****************************************/
 536
 537static const struct opp_funcs funcs = {
 538        .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
 539        .opp_destroy = dce110_opp_destroy,
 540        .opp_program_fmt = dce110_opp_program_fmt,
 541        .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction
 542};
 543
 544void dce110_opp_construct(struct dce110_opp *opp110,
 545        struct dc_context *ctx,
 546        uint32_t inst,
 547        const struct dce_opp_registers *regs,
 548        const struct dce_opp_shift *opp_shift,
 549        const struct dce_opp_mask *opp_mask)
 550{
 551        opp110->base.funcs = &funcs;
 552
 553        opp110->base.ctx = ctx;
 554
 555        opp110->base.inst = inst;
 556
 557        opp110->regs = regs;
 558        opp110->opp_shift = opp_shift;
 559        opp110->opp_mask = opp_mask;
 560}
 561
 562void dce110_opp_destroy(struct output_pixel_processor **opp)
 563{
 564        if (*opp)
 565                kfree(FROM_DCE11_OPP(*opp));
 566        *opp = NULL;
 567}
 568
 569