How do I combine these 2 queries

I wouldn’t combine the queries, primarily since they’re keying on different meta keys and values. The WP Query API is very powerful, but you’re trying to do some very advanced searching and sorting here.

One option would be to write a raw SQL query by hand and pass it into $wpdb->get_results(), but that won’t necessarily be future safe (i.e. if future versions change the DB schema).

Instead, I recommend you do both queries separately and merge the two arrays.

Some (very rough) psuedocode:

// Get your promotions using the arguments you outlined above.
$ongoing_promotions = get_posts( $ongoing_args );
$current_promotions = get_posts( $current_args );

// Merge the two arrays
$all_promotions = array_merge( $ongoing_promotions, $current_promotions );

// Get just the IDs of your promotions
$promotion_ids = wp_list_pluck( $all_promotions, 'ID' );

// Do a new query with these IDs to get a properly-sorted list of promotions
$promotions = get_posts( array(
    'post__in'    => $promotion_ids,
    'post_type'   => 'promotion',
    'post_status' => 'publish'
) );

// Now loop through your promotions
foreach( $posts as $post ) :   
    setup_postdata($post); ?>

<li>
    <a href="https://wordpress.stackexchange.com/questions/47721/<?php the_permalink(); ?>"><?php the_title(); ?></a>
    <br/>
    <span>
        <?php
        $meta = get_post_meta(get_the_ID(), 'sp_endDate', true);
        if ( '' != $meta ) {
            $formattedDate = new DateTime( $meta );
            echo "Expires: ".$formattedDate->format('F d, Y');
        }
        ?>
    </span>
</li>
<?php endforeach; ?>